From c59b70841c36277464b51161e3fcf12dfcb667e0 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 7 Mar 2025 10:13:30 +0800 Subject: Emit warning while outputs is not exe and prints linkage info Signed-off-by: xizheyin --- compiler/rustc_codegen_ssa/src/back/link.rs | 19 +++++++++++++++++++ .../emit-warning-print-link-info-without-staticlib.rs | 5 +++++ ...t-warning-print-link-info-without-staticlib.stderr | 6 ++++++ .../emit-warning-while-exe-and-print-link-info.rs | 3 +++ .../emit-warning-while-exe-and-print-link-info.stderr | 4 ++++ tests/ui/print-request/stability.rs | 1 + 6 files changed, 38 insertions(+) create mode 100644 tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs create mode 100644 tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr create mode 100644 tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs create mode 100644 tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 323538969d7..ffa888a17d0 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -68,6 +68,23 @@ pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { } } +fn check_link_info_print_request(sess: &Session, crate_type: CrateType) { + let print_native_static_libs = + sess.opts.prints.iter().any(|p| p.kind == PrintKind::NativeStaticLibs); + if print_native_static_libs { + if crate_type != CrateType::Staticlib { + sess.dcx() + .warn(format!("cannot output linkage information without staticlib crate-type")); + sess.dcx() + .note(format!("consider `--crate-type staticlib` to print linkage information")); + } else if !sess.opts.output_types.should_link() { + sess.dcx().warn(format!( + "skipping link step due to conflict: cannot output linkage information without emitting link" + )); + } + } +} + /// Performs the linkage portion of the compilation phase. This will generate all /// of the requested outputs for this compilation session. pub fn link_binary( @@ -178,6 +195,8 @@ pub fn link_binary( tempfiles_for_stdout_output.push(out_filename); } } + + check_link_info_print_request(sess, crate_type); } // Remove the temporary object file and metadata if we aren't saving temps. diff --git a/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs new file mode 100644 index 00000000000..b100c062bba --- /dev/null +++ b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs @@ -0,0 +1,5 @@ +//@ compile-flags: --print native-static-libs +//@ check-pass +//~? WARN cannot output linkage information without staticlib crate-type + +fn main() {} diff --git a/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr new file mode 100644 index 00000000000..ceff08baa13 --- /dev/null +++ b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr @@ -0,0 +1,6 @@ +warning: cannot output linkage information without staticlib crate-type + +note: consider `--crate-type staticlib` to print linkage information + +warning: 1 warning emitted + diff --git a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs new file mode 100644 index 00000000000..48f5475c884 --- /dev/null +++ b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs @@ -0,0 +1,3 @@ +//@ compile-flags: --print native-static-libs --crate-type staticlib --emit metadata +//@ check-pass +//~? WARN skipping link step due to conflict: cannot output linkage information without emitting link diff --git a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr new file mode 100644 index 00000000000..0b46d2f6848 --- /dev/null +++ b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr @@ -0,0 +1,4 @@ +warning: skipping link step due to conflict: cannot output linkage information without emitting link + +warning: 1 warning emitted + diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs index 54142ce78ce..fbcdf916cc7 100644 --- a/tests/ui/print-request/stability.rs +++ b/tests/ui/print-request/stability.rs @@ -110,3 +110,4 @@ fn main() {} //[check_cfg]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `check-cfg` print option //[supported_crate_types]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `supported-crate-types` print option //[target_spec_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `target-spec-json` print option +//[native_static_libs]~? WARNING cannot output linkage information without staticlib crate-type -- cgit 1.4.1-3-g733a5 From 98bb597c05c32365abbd6898f278b097352774ed Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 2 May 2025 22:37:33 +0800 Subject: Update compiler/rustc_codegen_ssa/src/back/link.rs Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ffa888a17d0..28c7b5b2745 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -79,7 +79,7 @@ fn check_link_info_print_request(sess: &Session, crate_type: CrateType) { .note(format!("consider `--crate-type staticlib` to print linkage information")); } else if !sess.opts.output_types.should_link() { sess.dcx().warn(format!( - "skipping link step due to conflict: cannot output linkage information without emitting link" + "cannot output linkage information when --emit link is not passed" )); } } -- cgit 1.4.1-3-g733a5 From 72a9219e82c157041bfc8dfd378c9cb2b09c0650 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 2 May 2025 22:56:27 +0800 Subject: check all crate-type to find staticlib Signed-off-by: xizheyin --- compiler/rustc_codegen_ssa/src/back/link.rs | 12 ++++++------ .../emit-warning-while-exe-and-print-link-info.rs | 2 +- .../emit-warning-while-exe-and-print-link-info.stderr | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 28c7b5b2745..1e9d9338b13 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -68,19 +68,19 @@ pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { } } -fn check_link_info_print_request(sess: &Session, crate_type: CrateType) { +fn check_link_info_print_request(sess: &Session, crate_types: &[CrateType]) { let print_native_static_libs = sess.opts.prints.iter().any(|p| p.kind == PrintKind::NativeStaticLibs); + let has_staticlib = crate_types.iter().any(|ct| *ct == CrateType::Staticlib); if print_native_static_libs { - if crate_type != CrateType::Staticlib { + if !has_staticlib { sess.dcx() .warn(format!("cannot output linkage information without staticlib crate-type")); sess.dcx() .note(format!("consider `--crate-type staticlib` to print linkage information")); } else if !sess.opts.output_types.should_link() { - sess.dcx().warn(format!( - "cannot output linkage information when --emit link is not passed" - )); + sess.dcx() + .warn(format!("cannot output linkage information when --emit link is not passed")); } } } @@ -196,7 +196,7 @@ pub fn link_binary( } } - check_link_info_print_request(sess, crate_type); + check_link_info_print_request(sess, &codegen_results.crate_info.crate_types); } // Remove the temporary object file and metadata if we aren't saving temps. diff --git a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs index 48f5475c884..3e9ca457a9c 100644 --- a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs +++ b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs @@ -1,3 +1,3 @@ //@ compile-flags: --print native-static-libs --crate-type staticlib --emit metadata //@ check-pass -//~? WARN skipping link step due to conflict: cannot output linkage information without emitting link +//~? WARN cannot output linkage information when --emit link is not passed diff --git a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr index 0b46d2f6848..b32e1437d6b 100644 --- a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr +++ b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr @@ -1,4 +1,4 @@ -warning: skipping link step due to conflict: cannot output linkage information without emitting link +warning: cannot output linkage information when --emit link is not passed warning: 1 warning emitted -- cgit 1.4.1-3-g733a5 From f66787a08d57dc1296619b314d2be596085bfeef Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 2 May 2025 23:14:18 +0800 Subject: Update compiler/rustc_codegen_ssa/src/back/link.rs Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> Signed-off-by: xizheyin --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1e9d9338b13..62c389ec791 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -195,10 +195,10 @@ pub fn link_binary( tempfiles_for_stdout_output.push(out_filename); } } - - check_link_info_print_request(sess, &codegen_results.crate_info.crate_types); } + check_link_info_print_request(sess, &codegen_results.crate_info.crate_types); + // Remove the temporary object file and metadata if we aren't saving temps. sess.time("link_binary_remove_temps", || { // If the user requests that temporaries are saved, don't delete any. -- cgit 1.4.1-3-g733a5 From 06da7b31ac227edb12fbf9e3760d2fb42fe7084c Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Mon, 12 May 2025 23:08:54 +0800 Subject: fixes: ide-assists, generate_new indent loses --- .../ide-assists/src/handlers/generate_new.rs | 137 ++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs index f963f48d62a..4837f92f934 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs @@ -129,17 +129,23 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option // Get the mutable version of the impl to modify let impl_def = if let Some(impl_def) = impl_def { + fn_.indent(impl_def.indent_level()); builder.make_mut(impl_def) } else { // Generate a new impl to add the method to let impl_def = generate_impl(&ast::Adt::Struct(strukt.clone())); + let indent_level = strukt.indent_level(); + fn_.indent(indent_level); // Insert it after the adt let strukt = builder.make_mut(strukt.clone()); ted::insert_all_raw( ted::Position::after(strukt.syntax()), - vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], + vec![ + make::tokens::whitespace(&format!("\n\n{indent_level}")).into(), + impl_def.syntax().clone().into(), + ], ); impl_def @@ -425,6 +431,135 @@ impl Foo { ); } + #[test] + fn non_zero_indent() { + check_assist( + generate_new, + r#" +mod foo { + struct $0Foo {} +} +"#, + r#" +mod foo { + struct Foo {} + + impl Foo { + fn $0new() -> Self { + Self { } + } + } +} +"#, + ); + check_assist( + generate_new, + r#" +mod foo { + mod bar { + struct $0Foo {} + } +} +"#, + r#" +mod foo { + mod bar { + struct Foo {} + + impl Foo { + fn $0new() -> Self { + Self { } + } + } + } +} +"#, + ); + check_assist( + generate_new, + r#" +mod foo { + struct $0Foo {} + + impl Foo { + fn some() {} + } +} +"#, + r#" +mod foo { + struct Foo {} + + impl Foo { + fn $0new() -> Self { + Self { } + } + + fn some() {} + } +} +"#, + ); + check_assist( + generate_new, + r#" +mod foo { + mod bar { + struct $0Foo {} + + impl Foo { + fn some() {} + } + } +} +"#, + r#" +mod foo { + mod bar { + struct Foo {} + + impl Foo { + fn $0new() -> Self { + Self { } + } + + fn some() {} + } + } +} +"#, + ); + check_assist( + generate_new, + r#" +mod foo { + mod bar { +struct $0Foo {} + + impl Foo { + fn some() {} + } + } +} +"#, + r#" +mod foo { + mod bar { +struct Foo {} + + impl Foo { + fn $0new() -> Self { + Self { } + } + + fn some() {} + } + } +} +"#, + ); + } + #[test] fn check_visibility_of_new_fn_based_on_struct() { check_assist( -- cgit 1.4.1-3-g733a5 From 6a35b51860ecf1b9ecbbe6d02579dcd53291e006 Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Wed, 14 May 2025 23:02:32 +0800 Subject: fix: ide-assists, generate mut trait impl indent --- .../src/handlers/generate_mut_trait_impl.rs | 94 +++++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs index 2ac960ed7e1..bab2ccf3f33 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -1,7 +1,7 @@ use ide_db::famous_defs::FamousDefs; use syntax::{ AstNode, - ast::{self, make}, + ast::{self, edit_in_place::Indent, make}, ted, }; @@ -46,6 +46,7 @@ use crate::{AssistContext, AssistId, Assists}; // ``` pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let impl_def = ctx.find_node_at_offset::()?.clone_for_update(); + let indent = impl_def.indent_level(); let trait_ = impl_def.trait_()?; if let ast::Type::PathType(trait_path) = trait_ { @@ -97,8 +98,8 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_> })?; let assoc_list = make::assoc_item_list().clone_for_update(); - assoc_list.add_item(syntax::ast::AssocItem::Fn(fn_)); ted::replace(impl_def.assoc_item_list()?.syntax(), assoc_list.syntax()); + impl_def.get_or_create_assoc_item_list().add_item(syntax::ast::AssocItem::Fn(fn_)); let target = impl_def.syntax().text_range(); acc.add( @@ -106,7 +107,7 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_> "Generate `IndexMut` impl from this `Index` trait", target, |edit| { - edit.insert(target.start(), format!("$0{impl_def}\n\n")); + edit.insert(target.start(), format!("$0{impl_def}\n\n{indent}")); }, ) } @@ -189,6 +190,93 @@ impl core::ops::Index for [T; 3] where T: Copy { ); } + #[test] + fn test_generate_mut_trait_impl_non_zero_indent() { + check_assist( + generate_mut_trait_impl, + r#" +//- minicore: index +mod foo { + pub enum Axis { X = 0, Y = 1, Z = 2 } + + impl core::ops::Index$0 for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } + } +} +"#, + r#" +mod foo { + pub enum Axis { X = 0, Y = 1, Z = 2 } + + $0impl core::ops::IndexMut for [T; 3] where T: Copy { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + let var_name = &self[index as usize]; + var_name + } + } + + impl core::ops::Index for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } + } +} +"#, + ); + + check_assist( + generate_mut_trait_impl, + r#" +//- minicore: index +mod foo { + mod bar { + pub enum Axis { X = 0, Y = 1, Z = 2 } + + impl core::ops::Index$0 for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } + } + } +} +"#, + r#" +mod foo { + mod bar { + pub enum Axis { X = 0, Y = 1, Z = 2 } + + $0impl core::ops::IndexMut for [T; 3] where T: Copy { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + let var_name = &self[index as usize]; + var_name + } + } + + impl core::ops::Index for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } + } + } +} +"#, + ); + } + #[test] fn test_generate_mut_trait_impl_not_applicable() { check_assist_not_applicable( -- cgit 1.4.1-3-g733a5 From 687eeeafc8031f143698304b34d5fbdce6bb8e0e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 19 May 2025 08:40:59 +0200 Subject: Change import prefix default to be by crate The current default plain, tends to create non-uniform import blocks over time, some being relative, some being absolute. I believe we should encourage a different default here. --- src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs | 2 +- src/tools/rust-analyzer/docs/book/src/configuration_generated.md | 2 +- src/tools/rust-analyzer/editors/code/package.json | 2 +- 3 files changed, 3 insertions(+), 3 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 03e5b1f6f4b..f7158235ca4 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -544,7 +544,7 @@ config_data! { /// Whether to prefer import paths containing a `prelude` module. imports_preferPrelude: bool = false, /// The path structure for newly inserted paths to use. - imports_prefix: ImportPrefixDef = ImportPrefixDef::Plain, + imports_prefix: ImportPrefixDef = ImportPrefixDef::ByCrate, /// Whether to prefix external (including std, core) crate imports with `::`. e.g. "use ::std::io::Read;". imports_prefixExternPrelude: bool = false, } diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index 2ae73df61d0..de1d0ea4a35 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -835,7 +835,7 @@ Whether to prefer import paths containing a `prelude` module. ## rust-analyzer.imports.prefix {#imports.prefix} -Default: `"plain"` +Default: `"crate"` The path structure for newly inserted paths to use. diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index a282eea9997..88a90aad8c9 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -1927,7 +1927,7 @@ "properties": { "rust-analyzer.imports.prefix": { "markdownDescription": "The path structure for newly inserted paths to use.", - "default": "plain", + "default": "crate", "type": "string", "enum": [ "plain", -- cgit 1.4.1-3-g733a5 From 31b4808432efc02ead21199f498ee9e68ac6724e Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 19 May 2025 15:34:00 +0300 Subject: Fix cache problems with lints level By removing the cache. --- .../ide-diagnostics/src/handlers/missing_unsafe.rs | 43 +++++ .../crates/ide-diagnostics/src/lib.rs | 181 ++------------------- 2 files changed, 60 insertions(+), 164 deletions(-) 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 364bead34ef..6bd5417b25d 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 @@ -915,4 +915,47 @@ fn foo() { "#, ); } + + #[test] + fn regression_19823() { + check_diagnostics( + r#" +pub trait FooTrait { + unsafe fn method1(); + unsafe fn method2(); +} + +unsafe fn some_unsafe_fn() {} + +macro_rules! impl_foo { + () => { + unsafe fn method1() { + some_unsafe_fn(); + } + unsafe fn method2() { + some_unsafe_fn(); + } + }; +} + +pub struct S1; +#[allow(unsafe_op_in_unsafe_fn)] +impl FooTrait for S1 { + unsafe fn method1() { + some_unsafe_fn(); + } + + unsafe fn method2() { + some_unsafe_fn(); + } +} + +pub struct S2; +#[allow(unsafe_op_in_unsafe_fn)] +impl FooTrait for S2 { + impl_foo!(); +} + "#, + ); + } } 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 2af14ca949b..72bd66d1c8b 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -83,12 +83,11 @@ mod handlers { #[cfg(test)] mod tests; -use std::{collections::hash_map, iter, sync::LazyLock}; +use std::{iter, sync::LazyLock}; use either::Either; use hir::{ - Crate, DisplayTarget, HirFileId, InFile, Semantics, db::ExpandDatabase, - diagnostics::AnyDiagnostic, + Crate, DisplayTarget, InFile, Semantics, db::ExpandDatabase, diagnostics::AnyDiagnostic, }; use ide_db::{ EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap, @@ -513,13 +512,7 @@ pub fn semantic_diagnostics( // The edition isn't accurate (each diagnostics may have its own edition due to macros), // but it's okay as it's only being used for error recovery. - handle_lints( - &ctx.sema, - &mut FxHashMap::default(), - &mut lints, - &mut Vec::new(), - editioned_file_id.edition(db), - ); + handle_lints(&ctx.sema, &mut lints, editioned_file_id.edition(db)); res.retain(|d| d.severity != Severity::Allow); @@ -584,8 +577,6 @@ fn handle_diag_from_macros( true } -// `__RA_EVERY_LINT` is a fake lint group to allow every lint in proc macros - struct BuiltLint { lint: &'static Lint, groups: Vec<&'static str>, @@ -629,9 +620,7 @@ fn build_lints_map( fn handle_lints( sema: &Semantics<'_, RootDatabase>, - cache: &mut FxHashMap>, diagnostics: &mut [(InFile, &mut Diagnostic)], - cache_stack: &mut Vec, edition: Edition, ) { for (node, diag) in diagnostics { @@ -645,7 +634,8 @@ fn handle_lints( diag.severity = default_severity; } - let mut diag_severity = fill_lint_attrs(sema, node, cache, cache_stack, diag, edition); + let mut diag_severity = + lint_severity_at(sema, node, &lint_groups(&diag.code, edition), edition); if let outline_diag_severity @ Some(_) = find_outline_mod_lint_severity(sema, node, diag, edition) @@ -698,155 +688,22 @@ fn find_outline_mod_lint_severity( result } -#[derive(Debug, Clone, Copy)] -struct SeverityAttr { - severity: Severity, - /// This field counts how far we are from the main node. Bigger values mean more far. - /// - /// Note this isn't accurate: there can be gaps between values (created when merging severity maps). - /// The important thing is that if an attr is closer to the main node, it will have smaller value. - /// - /// This is necessary even though we take care to never overwrite a value from deeper nesting - /// because of lint groups. For example, in the following code: - /// ``` - /// #[warn(non_snake_case)] - /// mod foo { - /// #[allow(nonstandard_style)] - /// mod bar {} - /// } - /// ``` - /// We want to not warn on non snake case inside `bar`. If we are traversing this for the first - /// time, everything will be fine, because we will set `diag_severity` on the first matching group - /// and never overwrite it since then. But if `bar` is cached, the cache will contain both - /// `#[warn(non_snake_case)]` and `#[allow(nonstandard_style)]`, and without this field, we have - /// no way of differentiating between the two. - depth: u32, -} - -fn fill_lint_attrs( +fn lint_severity_at( sema: &Semantics<'_, RootDatabase>, node: &InFile, - cache: &mut FxHashMap>, - cache_stack: &mut Vec, - diag: &Diagnostic, + lint_groups: &LintGroups, edition: Edition, ) -> Option { - let mut collected_lint_attrs = FxHashMap::::default(); - let mut diag_severity = None; - - let mut ancestors = node.value.ancestors().peekable(); - let mut depth = 0; - loop { - let ancestor = ancestors.next().expect("we always return from top-level nodes"); - depth += 1; - - if ancestors.peek().is_none() { - // We don't want to insert too many nodes into cache, but top level nodes (aka. outline modules - // or macro expansions) need to touch the database so they seem like a good fit to cache. - - if let Some(cached) = cache.get_mut(&node.file_id) { - // This node (and everything above it) is already cached; the attribute is either here or nowhere. - - // Workaround for the borrow checker. - let cached = std::mem::take(cached); - - cached.iter().for_each(|(lint, severity)| { - for item in &*cache_stack { - let node_cache_entry = cache - .get_mut(item) - .expect("we always insert cached nodes into the cache map"); - let lint_cache_entry = node_cache_entry.entry(lint.clone()); - if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry { - // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs - // overwrite top attrs. - lint_cache_entry.insert(SeverityAttr { - severity: severity.severity, - depth: severity.depth + depth, - }); - } - } - }); - - let lints = lint_groups(&diag.code, edition); - let all_matching_groups = - lints.iter().filter_map(|lint_group| cached.get(lint_group)); - let cached_severity = - all_matching_groups.min_by_key(|it| it.depth).map(|it| it.severity); - - cache.insert(node.file_id, cached); - - return diag_severity.or(cached_severity); - } - - // Insert this node's descendants' attributes into any outline descendant, but not including this node. - // This must come before inserting this node's own attributes to preserve order. - collected_lint_attrs.drain().for_each(|(lint, severity)| { - if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) { - diag_severity = Some(severity.severity); - } - - for item in &*cache_stack { - let node_cache_entry = cache - .get_mut(item) - .expect("we always insert cached nodes into the cache map"); - let lint_cache_entry = node_cache_entry.entry(lint.clone()); - if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry { - // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs - // overwrite top attrs. - lint_cache_entry.insert(severity); - } - } - }); - - cache_stack.push(node.file_id); - cache.insert(node.file_id, FxHashMap::default()); - - if let Some(ancestor) = ast::AnyHasAttrs::cast(ancestor) { - // Insert this node's attributes into any outline descendant, including this node. - lint_attrs(sema, ancestor, edition).for_each(|(lint, severity)| { - if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) { - diag_severity = Some(severity); - } - - for item in &*cache_stack { - let node_cache_entry = cache - .get_mut(item) - .expect("we always insert cached nodes into the cache map"); - let lint_cache_entry = node_cache_entry.entry(lint.clone()); - if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry { - // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs - // overwrite top attrs. - lint_cache_entry.insert(SeverityAttr { severity, depth }); - } - } - }); - } - - let parent_node = sema.find_parent_file(node.file_id); - if let Some(parent_node) = parent_node { - let parent_severity = - fill_lint_attrs(sema, &parent_node, cache, cache_stack, diag, edition); - if diag_severity.is_none() { - diag_severity = parent_severity; - } - } - cache_stack.pop(); - return diag_severity; - } else if let Some(ancestor) = ast::AnyHasAttrs::cast(ancestor) { - lint_attrs(sema, ancestor, edition).for_each(|(lint, severity)| { - if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) { - diag_severity = Some(severity); - } - - let lint_cache_entry = collected_lint_attrs.entry(lint); - if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry { - // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs - // overwrite top attrs. - lint_cache_entry.insert(SeverityAttr { severity, depth }); - } - }); - } - } + node.value + .ancestors() + .filter_map(ast::AnyHasAttrs::cast) + .find_map(|ancestor| { + lint_attrs(sema, ancestor, edition) + .find_map(|(lint, severity)| lint_groups.contains(&lint).then_some(severity)) + }) + .or_else(|| { + lint_severity_at(sema, &sema.find_parent_file(node.file_id)?, lint_groups, edition) + }) } fn lint_attrs<'a>( @@ -945,10 +802,6 @@ impl LintGroups { fn contains(&self, group: &str) -> bool { self.groups.contains(&group) || (self.inside_warnings && group == "warnings") } - - fn iter(&self) -> impl Iterator { - self.groups.iter().copied().chain(self.inside_warnings.then_some("warnings")) - } } fn lint_groups(lint: &DiagnosticCode, edition: Edition) -> LintGroups { -- cgit 1.4.1-3-g733a5 From b21c9e7bfb0180b67b486013a7137fb200cb1076 Mon Sep 17 00:00:00 2001 From: Marcelo Domínguez <69964857+Sa4dUs@users.noreply.github.com> Date: Tue, 6 May 2025 09:19:33 +0200 Subject: Split `autodiff` into `autodiff_forward` and `autodiff_reverse` Pending fix. ``` error: cannot find a built-in macro with name `autodiff_forward` --> library\core\src\macros\mod.rs:1542:5 | 1542 | / pub macro autodiff_forward($item:item) { 1543 | | /* compiler built-in */ 1544 | | } | |_____^ error: cannot find a built-in macro with name `autodiff_reverse` --> library\core\src\macros\mod.rs:1549:5 | 1549 | / pub macro autodiff_reverse($item:item) { 1550 | | /* compiler built-in */ 1551 | | } | |_____^ error: could not compile `core` (lib) due to 2 previous errors ``` --- compiler/rustc_builtin_macros/src/autodiff.rs | 41 ++++++++++++++++++--------- compiler/rustc_builtin_macros/src/lib.rs | 3 +- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_span/src/symbol.rs | 3 +- library/core/src/lib.rs | 2 +- library/core/src/macros/mod.rs | 14 +++++++++ 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 1ff4fc6aaab..8073de15925 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -88,25 +88,20 @@ mod llvm_enzyme { has_ret: bool, ) -> AutoDiffAttrs { let dcx = ecx.sess.dcx(); - let mode = name(&meta_item[1]); - let Ok(mode) = DiffMode::from_str(&mode) else { - dcx.emit_err(errors::AutoDiffInvalidMode { span: meta_item[1].span(), mode }); - return AutoDiffAttrs::error(); - }; // Now we check, whether the user wants autodiff in batch/vector mode, or scalar mode. // If he doesn't specify an integer (=width), we default to scalar mode, thus width=1. - let mut first_activity = 2; + let mut first_activity = 1; - let width = if let [_, _, x, ..] = &meta_item[..] + let width = if let [_, x, ..] = &meta_item[..] && let Some(x) = width(x) { - first_activity = 3; + first_activity = 2; match x.try_into() { Ok(x) => x, Err(_) => { dcx.emit_err(errors::AutoDiffInvalidWidth { - span: meta_item[2].span(), + span: meta_item[1].span(), width: x, }); return AutoDiffAttrs::error(); @@ -150,7 +145,7 @@ mod llvm_enzyme { }; AutoDiffAttrs { - mode, + mode: DiffMode::Error, width, ret_activity: *ret_activity, input_activity: input_activity.to_vec(), @@ -165,6 +160,24 @@ mod llvm_enzyme { ts.push(TokenTree::Token(comma.clone(), Spacing::Alone)); } + pub(crate) fn expand_forward( + ecx: &mut ExtCtxt<'_>, + expand_span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> Vec { + expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Forward) + } + + pub(crate) fn expand_reverse( + ecx: &mut ExtCtxt<'_>, + expand_span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> Vec { + expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Reverse) + } + /// We expand the autodiff macro to generate a new placeholder function which passes /// type-checking and can be called by users. The function body of the placeholder function will /// later be replaced on LLVM-IR level, so the design of the body is less important and for now @@ -198,11 +211,12 @@ mod llvm_enzyme { /// ``` /// FIXME(ZuseZ4): Once autodiff is enabled by default, make this a doc comment which is checked /// in CI. - pub(crate) fn expand( + pub(crate) fn expand_with_mode( ecx: &mut ExtCtxt<'_>, expand_span: Span, meta_item: &ast::MetaItem, mut item: Annotatable, + mode: DiffMode, ) -> Vec { if cfg!(not(llvm_enzyme)) { ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span }); @@ -289,7 +303,8 @@ mod llvm_enzyme { ts.pop(); let ts: TokenStream = TokenStream::from_iter(ts); - let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret); + let mut x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret); + x.mode = mode; if !x.is_active() { // We encountered an error, so we return the original item. // This allows us to potentially parse other attributes. @@ -1017,4 +1032,4 @@ mod llvm_enzyme { } } -pub(crate) use llvm_enzyme::expand; +pub(crate) use llvm_enzyme::{expand_forward, expand_reverse}; diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9cd4d17059a..a89b3642f7e 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -112,7 +112,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_attr! { alloc_error_handler: alloc_error_handler::expand, - autodiff: autodiff::expand, + autodiff_forward: autodiff::expand_forward, + autodiff_reverse: autodiff::expand_reverse, bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5c0d0cf4796..5aff24f7aa0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -255,7 +255,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - [sym::autodiff, ..] => { + [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } [sym::coroutine, ..] => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index efae6250b07..bb19b5761bb 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -531,7 +531,8 @@ symbols! { audit_that, augmented_assignments, auto_traits, - autodiff, + autodiff_forward, + autodiff_reverse, automatically_derived, avx, avx10_target_feature, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e605d7e0d78..aaa8c872f98 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -229,7 +229,7 @@ pub mod assert_matches { /// Unstable module containing the unstable `autodiff` macro. pub mod autodiff { #[unstable(feature = "autodiff", issue = "124509")] - pub use crate::macros::builtin::autodiff; + pub use crate::macros::builtin::{autodiff_forward, autodiff_reverse}; } #[unstable(feature = "contracts", issue = "128044")] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7dc8c060cd5..dc50ad6a090 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1536,6 +1536,20 @@ pub(crate) mod builtin { /* compiler built-in */ } + #[unstable(feature = "autodiff", issue = "124509")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + pub macro autodiff_forward($item:item) { + /* compiler built-in */ + } + + #[unstable(feature = "autodiff", issue = "124509")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + pub macro autodiff_reverse($item:item) { + /* compiler built-in */ + } + /// Asserts that a boolean expression is `true` at runtime. /// /// This will invoke the [`panic!`] macro if the provided expression cannot be -- cgit 1.4.1-3-g733a5 From 9efad3a87bb69ce62f9a5b1703e1b8decfe5c4a6 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sun, 27 Apr 2025 16:18:29 +0200 Subject: Add data_ptr method to Mutex and RwLock --- library/std/src/sync/poison/mutex.rs | 6 ++++++ library/std/src/sync/poison/rwlock.rs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 1c29c619edc..372bf0a3029 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -608,6 +608,12 @@ impl Mutex { let data = self.data.get_mut(); poison::map_result(self.poison.borrow(), |()| data) } + + /// Returns a raw pointer to the underlying data. + #[unstable(feature = "mutex_data_ptr", issue = "140368")] + pub fn data_ptr(&self) -> *mut T { + self.data.get() + } } #[stable(feature = "mutex_from", since = "1.24.0")] diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 6976c0a64e2..0b32a2f1be1 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -634,6 +634,12 @@ impl RwLock { let data = self.data.get_mut(); poison::map_result(self.poison.borrow(), |()| data) } + + /// Returns a raw pointer to the underlying data. + #[unstable(feature = "rwlock_data_ptr", issue = "140368")] + pub fn data_ptr(&self) -> *mut T { + self.data.get() + } } #[stable(feature = "rust1", since = "1.0.0")] -- cgit 1.4.1-3-g733a5 From 9d6c5a88a18405eb53e91645d35371ab089f0a37 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 21 May 2025 08:05:44 +0200 Subject: Add more docs to new data_ptr methods --- library/std/src/sync/poison/mutex.rs | 5 +++++ library/std/src/sync/poison/rwlock.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 372bf0a3029..30325be685c 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -610,6 +610,11 @@ impl Mutex { } /// Returns a raw pointer to the underlying data. + /// + /// The returned pointer is always non-null and properly aligned, but it is + /// the user's responsibility to ensure that any reads and writes through it + /// are properly synchronized to avoid data races, and that it is not read + /// or written through after the mutex is dropped. #[unstable(feature = "mutex_data_ptr", issue = "140368")] pub fn data_ptr(&self) -> *mut T { self.data.get() diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 0b32a2f1be1..a060e2ea57a 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -636,6 +636,11 @@ impl RwLock { } /// Returns a raw pointer to the underlying data. + /// + /// The returned pointer is always non-null and properly aligned, but it is + /// the user's responsibility to ensure that any reads and writes through it + /// are properly synchronized to avoid data races, and that it is not read + /// or written through after the lock is dropped. #[unstable(feature = "rwlock_data_ptr", issue = "140368")] pub fn data_ptr(&self) -> *mut T { self.data.get() -- cgit 1.4.1-3-g733a5 From 20589bd6050ff9596348c751231ac84b7538adb4 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 21 May 2025 08:06:04 +0200 Subject: Add ReentrantLock::data_ptr --- library/std/src/sync/reentrant_lock.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 96a4cf12659..727252f03a2 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -349,6 +349,17 @@ impl ReentrantLock { } } + /// Returns a raw pointer to the underlying data. + /// + /// The returned pointer is always non-null and properly aligned, but it is + /// the user's responsibility to ensure that any reads through it are + /// properly synchronized to avoid data races, and that it is not read + /// through after the lock is dropped. + #[unstable(feature = "reentrant_lock_data_ptr", issue = "140368")] + pub fn data_ptr(&self) -> *const T { + &raw const self.data + } + unsafe fn increment_lock_count(&self) -> Option<()> { unsafe { *self.lock_count.get() = (*self.lock_count.get()).checked_add(1)?; -- cgit 1.4.1-3-g733a5 From b725cf6af8c5a709828d649c86185b30872219ac Mon Sep 17 00:00:00 2001 From: Marcelo Domínguez Date: Sat, 10 May 2025 00:11:06 +0000 Subject: Disable autodiff bootstrapping --- compiler/rustc_builtin_macros/src/errors.rs | 8 ------ compiler/rustc_builtin_macros/src/lib.rs | 2 +- library/core/src/lib.rs | 1 + library/core/src/macros/mod.rs | 40 +++++++++++++++++------------ library/std/src/lib.rs | 7 +++-- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index b28f7d312d9..b3cc460abbf 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -187,14 +187,6 @@ mod autodiff { pub(crate) act: String, } - #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_mode)] - pub(crate) struct AutoDiffInvalidMode { - #[primary_span] - pub(crate) span: Span, - pub(crate) mode: String, - } - #[derive(Diagnostic)] #[diag(builtin_macros_autodiff_width)] pub(crate) struct AutoDiffInvalidWidth { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index a89b3642f7e..b16f3cff5cf 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,10 +5,10 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(not(bootstrap), feature(autodiff))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] -#![feature(autodiff)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index aaa8c872f98..e1982116994 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -226,6 +226,7 @@ pub mod assert_matches { // We don't export this through #[macro_export] for now, to avoid breakage. #[unstable(feature = "autodiff", issue = "124509")] +#[cfg(not(bootstrap))] /// Unstable module containing the unstable `autodiff` macro. pub mod autodiff { #[unstable(feature = "autodiff", issue = "124509")] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index dc50ad6a090..99a4ab52b6c 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1519,33 +1519,39 @@ pub(crate) mod builtin { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } - /// Automatic Differentiation macro which allows generating a new function to compute - /// the derivative of a given function. It may only be applied to a function. - /// The expected usage syntax is - /// `#[autodiff(NAME, MODE, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` - /// where: - /// NAME is a string that represents a valid function name. - /// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst. - /// INPUT_ACTIVITIES consists of one valid activity for each input parameter. - /// OUTPUT_ACTIVITY must not be set if we implicitly return nothing (or explicitly return - /// `-> ()`). Otherwise it must be set to one of the allowed activities. - #[unstable(feature = "autodiff", issue = "124509")] - #[allow_internal_unstable(rustc_attrs)] - #[rustc_builtin_macro] - pub macro autodiff($item:item) { - /* compiler built-in */ - } - + /// the derivative of a given function in the forward mode of differentiation. + /// It may only be applied to a function. + /// + /// The expected usage syntax is: + /// `#[autodiff_forward(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` + /// + /// - `NAME`: A string that represents a valid function name. + /// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter. + /// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing + /// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities. #[unstable(feature = "autodiff", issue = "124509")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] + #[cfg(not(bootstrap))] pub macro autodiff_forward($item:item) { /* compiler built-in */ } + /// Automatic Differentiation macro which allows generating a new function to compute + /// the derivative of a given function in the reverse mode of differentiation. + /// It may only be applied to a function. + /// + /// The expected usage syntax is: + /// `#[autodiff_reverse(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` + /// + /// - `NAME`: A string that represents a valid function name. + /// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter. + /// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing + /// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities. #[unstable(feature = "autodiff", issue = "124509")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] + #[cfg(not(bootstrap))] pub macro autodiff_reverse($item:item) { /* compiler built-in */ } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ef41b47384d..0ac674d9890 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -276,12 +276,12 @@ // tidy-alphabetical-start // stabilization was reverted after it hit beta +#![cfg_attr(not(bootstrap), feature(autodiff))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] #![feature(asm_experimental_arch)] -#![feature(autodiff)] #![feature(cfg_sanitizer_cfi)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] @@ -636,12 +636,15 @@ pub mod simd { #[doc(inline)] pub use crate::std_float::StdFloat; } + #[unstable(feature = "autodiff", issue = "124509")] +#[cfg(not(bootstrap))] /// This module provides support for automatic differentiation. pub mod autodiff { /// This macro handles automatic differentiation. - pub use core::autodiff::autodiff; + pub use core::autodiff::{autodiff_forward, autodiff_reverse}; } + #[stable(feature = "futures_api", since = "1.36.0")] pub mod task { //! Types and Traits for working with asynchronous tasks. -- cgit 1.4.1-3-g733a5 From 2041de7083c114025646220068d3943be517af4a Mon Sep 17 00:00:00 2001 From: Marcelo Domínguez Date: Sat, 10 May 2025 00:37:15 +0000 Subject: Update codegen and pretty tests UI tests are pending, will depend on error messages change. --- tests/codegen/autodiff/batched.rs | 8 ++++---- tests/codegen/autodiff/identical_fnc.rs | 6 +++--- tests/codegen/autodiff/inline.rs | 4 ++-- tests/codegen/autodiff/scalar.rs | 4 ++-- tests/codegen/autodiff/sret.rs | 4 ++-- tests/pretty/autodiff/autodiff_forward.pp | 2 +- tests/pretty/autodiff/autodiff_forward.rs | 30 +++++++++++++++--------------- tests/pretty/autodiff/autodiff_reverse.pp | 2 +- tests/pretty/autodiff/autodiff_reverse.rs | 12 ++++++------ tests/pretty/autodiff/inherent_impl.pp | 2 +- tests/pretty/autodiff/inherent_impl.rs | 4 ++-- 11 files changed, 39 insertions(+), 39 deletions(-) diff --git a/tests/codegen/autodiff/batched.rs b/tests/codegen/autodiff/batched.rs index e0047116405..d27aed50e6c 100644 --- a/tests/codegen/autodiff/batched.rs +++ b/tests/codegen/autodiff/batched.rs @@ -11,11 +11,11 @@ #![feature(autodiff)] -use std::autodiff::autodiff; +use std::autodiff::autodiff_forward; -#[autodiff(d_square3, Forward, Dual, DualOnly)] -#[autodiff(d_square2, Forward, 4, Dual, DualOnly)] -#[autodiff(d_square1, Forward, 4, Dual, Dual)] +#[autodiff_forward(d_square3, Dual, DualOnly)] +#[autodiff_forward(d_square2, 4, Dual, DualOnly)] +#[autodiff_forward(d_square1, 4, Dual, Dual)] #[no_mangle] fn square(x: &f32) -> f32 { x * x diff --git a/tests/codegen/autodiff/identical_fnc.rs b/tests/codegen/autodiff/identical_fnc.rs index 1c3277f52b4..1c25b3d09ab 100644 --- a/tests/codegen/autodiff/identical_fnc.rs +++ b/tests/codegen/autodiff/identical_fnc.rs @@ -11,14 +11,14 @@ // identical function calls in the LLVM-IR, while having two different calls in the Rust code. #![feature(autodiff)] -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; -#[autodiff(d_square, Reverse, Duplicated, Active)] +#[autodiff_reverse(d_square, Duplicated, Active)] fn square(x: &f64) -> f64 { x * x } -#[autodiff(d_square2, Reverse, Duplicated, Active)] +#[autodiff_reverse(d_square2, Duplicated, Active)] fn square2(x: &f64) -> f64 { x * x } diff --git a/tests/codegen/autodiff/inline.rs b/tests/codegen/autodiff/inline.rs index e90faa4aa38..65bed170207 100644 --- a/tests/codegen/autodiff/inline.rs +++ b/tests/codegen/autodiff/inline.rs @@ -4,9 +4,9 @@ #![feature(autodiff)] -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; -#[autodiff(d_square, Reverse, Duplicated, Active)] +#[autodiff_reverse(d_square, Duplicated, Active)] fn square(x: &f64) -> f64 { x * x } diff --git a/tests/codegen/autodiff/scalar.rs b/tests/codegen/autodiff/scalar.rs index 85358f5fcb6..096b4209e84 100644 --- a/tests/codegen/autodiff/scalar.rs +++ b/tests/codegen/autodiff/scalar.rs @@ -3,9 +3,9 @@ //@ needs-enzyme #![feature(autodiff)] -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; -#[autodiff(d_square, Reverse, Duplicated, Active)] +#[autodiff_reverse(d_square, Duplicated, Active)] #[no_mangle] fn square(x: &f64) -> f64 { x * x diff --git a/tests/codegen/autodiff/sret.rs b/tests/codegen/autodiff/sret.rs index 5ead90041ed..d2fa85e3e37 100644 --- a/tests/codegen/autodiff/sret.rs +++ b/tests/codegen/autodiff/sret.rs @@ -9,10 +9,10 @@ #![feature(autodiff)] -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; #[no_mangle] -#[autodiff(df, Reverse, Active, Active, Active)] +#[autodiff_reverse(df, Active, Active, Active)] fn primal(x: f32, y: f32) -> f64 { (x * x * y) as f64 } diff --git a/tests/pretty/autodiff/autodiff_forward.pp b/tests/pretty/autodiff/autodiff_forward.pp index 8253603e807..a2525abc832 100644 --- a/tests/pretty/autodiff/autodiff_forward.pp +++ b/tests/pretty/autodiff/autodiff_forward.pp @@ -13,7 +13,7 @@ extern crate std; // Test that forward mode ad macros are expanded correctly. -use std::autodiff::autodiff; +use std::autodiff::{autodiff_forward, autodiff_reverse}; #[rustc_autodiff] #[inline(never)] diff --git a/tests/pretty/autodiff/autodiff_forward.rs b/tests/pretty/autodiff/autodiff_forward.rs index ae974f9b4db..181b6ebc770 100644 --- a/tests/pretty/autodiff/autodiff_forward.rs +++ b/tests/pretty/autodiff/autodiff_forward.rs @@ -7,48 +7,48 @@ // Test that forward mode ad macros are expanded correctly. -use std::autodiff::autodiff; +use std::autodiff::{autodiff_forward, autodiff_reverse}; -#[autodiff(df1, Forward, Dual, Const, Dual)] +#[autodiff_forward(df1, Dual, Const, Dual)] pub fn f1(x: &[f64], y: f64) -> f64 { unimplemented!() } -#[autodiff(df2, Forward, Dual, Const, Const)] +#[autodiff_forward(df2, Dual, Const, Const)] pub fn f2(x: &[f64], y: f64) -> f64 { unimplemented!() } -#[autodiff(df3, Forward, Dual, Const, Const)] +#[autodiff_forward(df3, Dual, Const, Const)] pub fn f3(x: &[f64], y: f64) -> f64 { unimplemented!() } // Not the most interesting derivative, but who are we to judge -#[autodiff(df4, Forward)] +#[autodiff_forward(df4)] pub fn f4() {} // We want to be sure that the same function can be differentiated in different ways -#[autodiff(df5_rev, Reverse, Duplicated, Const, Active)] -#[autodiff(df5_x, Forward, Dual, Const, Const)] -#[autodiff(df5_y, Forward, Const, Dual, Const)] +#[autodiff_reverse(df5_rev, Duplicated, Const, Active)] +#[autodiff_forward(df5_x, Dual, Const, Const)] +#[autodiff_forward(df5_y, Const, Dual, Const)] pub fn f5(x: &[f64], y: f64) -> f64 { unimplemented!() } struct DoesNotImplDefault; -#[autodiff(df6, Forward, Const)] +#[autodiff_forward(df6, Const)] pub fn f6() -> DoesNotImplDefault { unimplemented!() } // Make sure, that we add the None for the default return. -#[autodiff(df7, Forward, Const)] +#[autodiff_forward(df7, Const)] pub fn f7(x: f32) -> () {} -#[autodiff(f8_1, Forward, Dual, DualOnly)] -#[autodiff(f8_2, Forward, 4, Dual, DualOnly)] -#[autodiff(f8_3, Forward, 4, Dual, Dual)] +#[autodiff_forward(f8_1, Dual, DualOnly)] +#[autodiff_forward(f8_2, 4, Dual, DualOnly)] +#[autodiff_forward(f8_3, 4, Dual, Dual)] #[no_mangle] fn f8(x: &f32) -> f32 { unimplemented!() @@ -56,8 +56,8 @@ fn f8(x: &f32) -> f32 { // We want to make sure that we can use the macro for functions defined inside of functions pub fn f9() { - #[autodiff(d_inner_1, Forward, Dual, DualOnly)] - #[autodiff(d_inner_2, Forward, Dual, Dual)] + #[autodiff_forward(d_inner_1, Dual, DualOnly)] + #[autodiff_forward(d_inner_2, Dual, Dual)] fn inner(x: f32) -> f32 { x * x } diff --git a/tests/pretty/autodiff/autodiff_reverse.pp b/tests/pretty/autodiff/autodiff_reverse.pp index 31920694a3a..e67c3443dde 100644 --- a/tests/pretty/autodiff/autodiff_reverse.pp +++ b/tests/pretty/autodiff/autodiff_reverse.pp @@ -13,7 +13,7 @@ extern crate std; // Test that reverse mode ad macros are expanded correctly. -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; #[rustc_autodiff] #[inline(never)] diff --git a/tests/pretty/autodiff/autodiff_reverse.rs b/tests/pretty/autodiff/autodiff_reverse.rs index 3c024272f40..d37e5e3eb4c 100644 --- a/tests/pretty/autodiff/autodiff_reverse.rs +++ b/tests/pretty/autodiff/autodiff_reverse.rs @@ -7,18 +7,18 @@ // Test that reverse mode ad macros are expanded correctly. -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; -#[autodiff(df1, Reverse, Duplicated, Const, Active)] +#[autodiff_reverse(df1, Duplicated, Const, Active)] pub fn f1(x: &[f64], y: f64) -> f64 { unimplemented!() } // Not the most interesting derivative, but who are we to judge -#[autodiff(df2, Reverse)] +#[autodiff_reverse(df2)] pub fn f2() {} -#[autodiff(df3, Reverse, Duplicated, Const, Active)] +#[autodiff_reverse(df3, Duplicated, Const, Active)] pub fn f3(x: &[f64], y: f64) -> f64 { unimplemented!() } @@ -27,12 +27,12 @@ enum Foo { Reverse } use Foo::Reverse; // What happens if we already have Reverse in type (enum variant decl) and value (enum variant // constructor) namespace? > It's expected to work normally. -#[autodiff(df4, Reverse, Const)] +#[autodiff_reverse(df4, Const)] pub fn f4(x: f32) { unimplemented!() } -#[autodiff(df5, Reverse, DuplicatedOnly, Duplicated)] +#[autodiff_reverse(df5, DuplicatedOnly, Duplicated)] pub fn f5(x: *const f32, y: &f32) { unimplemented!() } diff --git a/tests/pretty/autodiff/inherent_impl.pp b/tests/pretty/autodiff/inherent_impl.pp index 97ac766b6b9..d18061b2dbd 100644 --- a/tests/pretty/autodiff/inherent_impl.pp +++ b/tests/pretty/autodiff/inherent_impl.pp @@ -11,7 +11,7 @@ extern crate std; //@ pretty-compare-only //@ pp-exact:inherent_impl.pp -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; struct Foo { a: f64, diff --git a/tests/pretty/autodiff/inherent_impl.rs b/tests/pretty/autodiff/inherent_impl.rs index 59de93f7e0f..11ff209f9d8 100644 --- a/tests/pretty/autodiff/inherent_impl.rs +++ b/tests/pretty/autodiff/inherent_impl.rs @@ -5,7 +5,7 @@ //@ pretty-compare-only //@ pp-exact:inherent_impl.pp -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; struct Foo { a: f64, @@ -17,7 +17,7 @@ trait MyTrait { } impl MyTrait for Foo { - #[autodiff(df, Reverse, Const, Active, Active)] + #[autodiff_reverse(df, Const, Active, Active)] fn f(&self, x: f64) -> f64 { self.a * 0.25 * (x * x - 1.0 - 2.0 * x.ln()) } -- cgit 1.4.1-3-g733a5 From f92d84cc6e0770c0d8f3dc775bafdf7f8786db61 Mon Sep 17 00:00:00 2001 From: Marcelo Domínguez Date: Sat, 10 May 2025 00:52:47 +0000 Subject: Initial naive implementation using `Symbols` to represent autodiff modes (`Forward`, `Reverse`) Since the mode is no longer part of `meta_item`, we must insert it manually (otherwise macro expansion with `#[rustc_autodiff]` won't work). This can be revised later if a more structured representation becomes necessary (using enums, annotated structs, etc). Some tests are currently failing. I'll address them next. --- compiler/rustc_builtin_macros/src/autodiff.rs | 28 +++++++++++++++++++-------- compiler/rustc_span/src/symbol.rs | 2 ++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 8073de15925..d60bb0ae5cb 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -259,29 +259,41 @@ mod llvm_enzyme { // create TokenStream from vec elemtents: // meta_item doesn't have a .tokens field let mut ts: Vec = vec![]; - if meta_item_vec.len() < 2 { - // At the bare minimum, we need a fnc name and a mode, even for a dummy function with no - // input and output args. + if meta_item_vec.len() < 1 { + // At the bare minimum, we need a fnc name. dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() }); return vec![item]; } - meta_item_inner_to_ts(&meta_item_vec[1], &mut ts); + let mode_symbol = match mode { + DiffMode::Forward => sym::Forward, + DiffMode::Reverse => sym::Reverse, + _ => unreachable!("Unsupported mode: {:?}", mode), + }; + + // Insert mode token + let mode_token = Token::new(TokenKind::Ident(mode_symbol, false.into()), Span::default()); + ts.insert(0, TokenTree::Token(mode_token, Spacing::Joint)); + ts.insert( + 1, + TokenTree::Token(Token::new(TokenKind::Comma, Span::default()), Spacing::Alone), + ); // Now, if the user gave a width (vector aka batch-mode ad), then we copy it. // If it is not given, we default to 1 (scalar mode). let start_position; let kind: LitKind = LitKind::Integer; let symbol; - if meta_item_vec.len() >= 3 - && let Some(width) = width(&meta_item_vec[2]) + if meta_item_vec.len() >= 2 + && let Some(width) = width(&meta_item_vec[1]) { - start_position = 3; + start_position = 2; symbol = Symbol::intern(&width.to_string()); } else { - start_position = 2; + start_position = 1; symbol = sym::integer(1); } + let l: Lit = Lit { kind, symbol, suffix: None }; let t = Token::new(TokenKind::Literal(l), Span::default()); let comma = Token::new(TokenKind::Comma, Span::default()); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index bb19b5761bb..9dff87e0a00 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -253,6 +253,7 @@ symbols! { FnMut, FnOnce, Formatter, + Forward, From, FromIterator, FromResidual, @@ -348,6 +349,7 @@ symbols! { Result, ResumeTy, Return, + Reverse, Right, Rust, RustaceansAreAwesome, -- cgit 1.4.1-3-g733a5 From 8dd62e8188d08baeb5d28cb221241cb61a65e532 Mon Sep 17 00:00:00 2001 From: Marcelo Domínguez Date: Sat, 10 May 2025 21:50:06 +0000 Subject: Update UI tests --- compiler/rustc_builtin_macros/messages.ftl | 1 - compiler/rustc_builtin_macros/src/autodiff.rs | 6 +- tests/ui/autodiff/autodiff_illegal.rs | 60 ++++++---------- tests/ui/autodiff/autodiff_illegal.stderr | 83 +++++++++------------- tests/ui/autodiff/auxiliary/my_macro.rs | 2 +- tests/ui/autodiff/visibility.rs | 9 ++- tests/ui/autodiff/visibility.std_autodiff.stderr | 26 +++---- .../feature-gate-autodiff-use.has_support.stderr | 8 +-- .../feature-gate-autodiff-use.no_support.stderr | 12 ++-- .../ui/feature-gates/feature-gate-autodiff-use.rs | 4 +- .../feature-gate-autodiff.has_support.stderr | 8 +-- .../feature-gate-autodiff.no_support.stderr | 8 +-- tests/ui/feature-gates/feature-gate-autodiff.rs | 6 +- 13 files changed, 101 insertions(+), 132 deletions(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 73be954cefd..4796f3a1888 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -71,7 +71,6 @@ builtin_macros_assert_requires_expression = macro requires an expression as an a builtin_macros_autodiff = autodiff must be applied to function builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode -builtin_macros_autodiff_mode = unknown Mode: `{$mode}`. Use `Forward` or `Reverse` builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode builtin_macros_autodiff_not_build = this rustc version does not support autodiff builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found} diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index d60bb0ae5cb..dc3bb8ab52a 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -86,6 +86,7 @@ mod llvm_enzyme { ecx: &mut ExtCtxt<'_>, meta_item: &ThinVec, has_ret: bool, + mode: DiffMode, ) -> AutoDiffAttrs { let dcx = ecx.sess.dcx(); @@ -145,7 +146,7 @@ mod llvm_enzyme { }; AutoDiffAttrs { - mode: DiffMode::Error, + mode, width, ret_activity: *ret_activity, input_activity: input_activity.to_vec(), @@ -315,8 +316,7 @@ mod llvm_enzyme { ts.pop(); let ts: TokenStream = TokenStream::from_iter(ts); - let mut x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret); - x.mode = mode; + let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret, mode); if !x.is_active() { // We encountered an error, so we return the original item. // This allows us to potentially parse other attributes. diff --git a/tests/ui/autodiff/autodiff_illegal.rs b/tests/ui/autodiff/autodiff_illegal.rs index a916bd8b857..a53b6d5e589 100644 --- a/tests/ui/autodiff/autodiff_illegal.rs +++ b/tests/ui/autodiff/autodiff_illegal.rs @@ -7,38 +7,38 @@ // Test that invalid ad macros give nice errors and don't ICE. -use std::autodiff::autodiff; +use std::autodiff::{autodiff_forward, autodiff_reverse}; // We can't use Duplicated on scalars -#[autodiff(df1, Reverse, Duplicated)] +#[autodiff_reverse(df1, Duplicated)] pub fn f1(x: f64) { //~^ ERROR Duplicated can not be used for this type unimplemented!() } // Too many activities -#[autodiff(df3, Reverse, Duplicated, Const)] +#[autodiff_reverse(df3, Duplicated, Const)] pub fn f3(x: f64) { //~^^ ERROR expected 1 activities, but found 2 unimplemented!() } // To few activities -#[autodiff(df4, Reverse)] +#[autodiff_reverse(df4)] pub fn f4(x: f64) { //~^^ ERROR expected 1 activities, but found 0 unimplemented!() } // We can't use Dual in Reverse mode -#[autodiff(df5, Reverse, Dual)] +#[autodiff_reverse(df5, Dual)] pub fn f5(x: f64) { //~^^ ERROR Dual can not be used in Reverse Mode unimplemented!() } // We can't use Duplicated in Forward mode -#[autodiff(df6, Forward, Duplicated)] +#[autodiff_forward(df6, Duplicated)] pub fn f6(x: f64) { //~^^ ERROR Duplicated can not be used in Forward Mode //~^^ ERROR Duplicated can not be used for this type @@ -46,36 +46,36 @@ pub fn f6(x: f64) { } fn dummy() { - #[autodiff(df7, Forward, Dual)] + #[autodiff_forward(df7, Dual)] let mut x = 5; //~^ ERROR autodiff must be applied to function - #[autodiff(df7, Forward, Dual)] + #[autodiff_forward(df7, Dual)] x = x + 3; //~^^ ERROR attributes on expressions are experimental [E0658] //~^^ ERROR autodiff must be applied to function - #[autodiff(df7, Forward, Dual)] + #[autodiff_forward(df7, Dual)] let add_one_v2 = |x: u32| -> u32 { x + 1 }; //~^ ERROR autodiff must be applied to function } // Malformed, where args? -#[autodiff] +#[autodiff_forward] pub fn f7(x: f64) { //~^ ERROR autodiff requires at least a name and mode unimplemented!() } // Malformed, where args? -#[autodiff()] +#[autodiff_forward()] pub fn f8(x: f64) { //~^ ERROR autodiff requires at least a name and mode unimplemented!() } // Invalid attribute syntax -#[autodiff = ""] +#[autodiff_forward = ""] pub fn f9(x: f64) { //~^ ERROR autodiff requires at least a name and mode unimplemented!() @@ -84,29 +84,15 @@ pub fn f9(x: f64) { fn fn_exists() {} // We colide with an already existing function -#[autodiff(fn_exists, Reverse, Active)] +#[autodiff_reverse(fn_exists, Active)] pub fn f10(x: f64) { //~^^ ERROR the name `fn_exists` is defined multiple times [E0428] unimplemented!() } -// Malformed, missing a mode -#[autodiff(df11)] -pub fn f11() { - //~^ ERROR autodiff requires at least a name and mode - unimplemented!() -} - -// Invalid Mode -#[autodiff(df12, Debug)] -pub fn f12() { - //~^^ ERROR unknown Mode: `Debug`. Use `Forward` or `Reverse` - unimplemented!() -} - // Invalid, please pick one Mode // or use two autodiff macros. -#[autodiff(df13, Forward, Reverse)] +#[autodiff_reverse(df13, Reverse)] pub fn f13() { //~^^ ERROR did not recognize Activity: `Reverse` unimplemented!() @@ -117,7 +103,7 @@ struct Foo {} // We can't handle Active structs, because that would mean (in the general case), that we would // need to allocate and initialize arbitrary user types. We have Duplicated/Dual input args for // that. FIXME: Give a nicer error and suggest to the user to have a `&mut Foo` input instead. -#[autodiff(df14, Reverse, Active, Active)] +#[autodiff_reverse(df14, Active, Active)] fn f14(x: f32) -> Foo { unimplemented!() } @@ -127,14 +113,14 @@ type MyFloat = f32; // We would like to support type alias to f32/f64 in argument type in the future, // but that requires us to implement our checks at a later stage // like THIR which has type information available. -#[autodiff(df15, Reverse, Active, Active)] +#[autodiff_reverse(df15, Active, Active)] fn f15(x: MyFloat) -> f32 { //~^^ ERROR failed to resolve: use of undeclared type `MyFloat` [E0433] unimplemented!() } // We would like to support type alias to f32/f64 in return type in the future -#[autodiff(df16, Reverse, Active, Active)] +#[autodiff_reverse(df16, Active, Active)] fn f16(x: f32) -> MyFloat { unimplemented!() } @@ -145,40 +131,40 @@ struct F64Trans { } // We would like to support `#[repr(transparent)]` f32/f64 wrapper in return type in the future -#[autodiff(df17, Reverse, Active, Active)] +#[autodiff_reverse(df17, Active, Active)] fn f17(x: f64) -> F64Trans { unimplemented!() } // We would like to support `#[repr(transparent)]` f32/f64 wrapper in argument type in the future -#[autodiff(df18, Reverse, Active, Active)] +#[autodiff_reverse(df18, Active, Active)] fn f18(x: F64Trans) -> f64 { //~^^ ERROR failed to resolve: use of undeclared type `F64Trans` [E0433] unimplemented!() } // Invalid return activity -#[autodiff(df19, Forward, Dual, Active)] +#[autodiff_forward(df19, Dual, Active)] fn f19(x: f32) -> f32 { //~^^ ERROR invalid return activity Active in Forward Mode unimplemented!() } -#[autodiff(df20, Reverse, Active, Dual)] +#[autodiff_reverse(df20, Active, Dual)] fn f20(x: f32) -> f32 { //~^^ ERROR invalid return activity Dual in Reverse Mode unimplemented!() } // Duplicated cannot be used as return activity -#[autodiff(df21, Reverse, Active, Duplicated)] +#[autodiff_reverse(df21, Active, Duplicated)] fn f21(x: f32) -> f32 { //~^^ ERROR invalid return activity Duplicated in Reverse Mode unimplemented!() } struct DoesNotImplDefault; -#[autodiff(df22, Forward, Dual)] +#[autodiff_forward(df22, Dual)] pub fn f22() -> DoesNotImplDefault { //~^^ ERROR the function or associated item `default` exists for tuple `(DoesNotImplDefault, DoesNotImplDefault)`, but its trait bounds were not satisfied unimplemented!() diff --git a/tests/ui/autodiff/autodiff_illegal.stderr b/tests/ui/autodiff/autodiff_illegal.stderr index b119f61b8ae..ad6f10af467 100644 --- a/tests/ui/autodiff/autodiff_illegal.stderr +++ b/tests/ui/autodiff/autodiff_illegal.stderr @@ -1,8 +1,8 @@ error[E0658]: attributes on expressions are experimental --> $DIR/autodiff_illegal.rs:53:5 | -LL | #[autodiff(df7, Forward, Dual)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_forward(df7, Dual)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable @@ -17,26 +17,26 @@ LL | pub fn f1(x: f64) { error: expected 1 activities, but found 2 --> $DIR/autodiff_illegal.rs:20:1 | -LL | #[autodiff(df3, Reverse, Duplicated, Const)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_reverse(df3, Duplicated, Const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected 1 activities, but found 0 --> $DIR/autodiff_illegal.rs:27:1 | -LL | #[autodiff(df4, Reverse)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_reverse(df4)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: Dual can not be used in Reverse Mode --> $DIR/autodiff_illegal.rs:34:1 | -LL | #[autodiff(df5, Reverse, Dual)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_reverse(df5, Dual)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Duplicated can not be used in Forward Mode --> $DIR/autodiff_illegal.rs:41:1 | -LL | #[autodiff(df6, Forward, Duplicated)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_forward(df6, Duplicated)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Duplicated can not be used for this type --> $DIR/autodiff_illegal.rs:42:14 @@ -95,69 +95,54 @@ error[E0428]: the name `fn_exists` is defined multiple times LL | fn fn_exists() {} | -------------- previous definition of the value `fn_exists` here ... -LL | #[autodiff(fn_exists, Reverse, Active)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn_exists` redefined here +LL | #[autodiff_reverse(fn_exists, Active)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn_exists` redefined here | = note: `fn_exists` must be defined only once in the value namespace of this module -error: autodiff requires at least a name and mode - --> $DIR/autodiff_illegal.rs:95:1 - | -LL | / pub fn f11() { -LL | | -LL | | unimplemented!() -LL | | } - | |_^ - -error: unknown Mode: `Debug`. Use `Forward` or `Reverse` - --> $DIR/autodiff_illegal.rs:101:18 - | -LL | #[autodiff(df12, Debug)] - | ^^^^^ - error: did not recognize Activity: `Reverse` - --> $DIR/autodiff_illegal.rs:109:27 + --> $DIR/autodiff_illegal.rs:95:26 | -LL | #[autodiff(df13, Forward, Reverse)] - | ^^^^^^^ +LL | #[autodiff_reverse(df13, Reverse)] + | ^^^^^^^ error: invalid return activity Active in Forward Mode - --> $DIR/autodiff_illegal.rs:161:1 + --> $DIR/autodiff_illegal.rs:147:1 | -LL | #[autodiff(df19, Forward, Dual, Active)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_forward(df19, Dual, Active)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid return activity Dual in Reverse Mode - --> $DIR/autodiff_illegal.rs:167:1 + --> $DIR/autodiff_illegal.rs:153:1 | -LL | #[autodiff(df20, Reverse, Active, Dual)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_reverse(df20, Active, Dual)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid return activity Duplicated in Reverse Mode - --> $DIR/autodiff_illegal.rs:174:1 + --> $DIR/autodiff_illegal.rs:160:1 | -LL | #[autodiff(df21, Reverse, Active, Duplicated)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_reverse(df21, Active, Duplicated)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared type `MyFloat` - --> $DIR/autodiff_illegal.rs:130:1 + --> $DIR/autodiff_illegal.rs:116:1 | -LL | #[autodiff(df15, Reverse, Active, Active)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `MyFloat` +LL | #[autodiff_reverse(df15, Active, Active)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `MyFloat` error[E0433]: failed to resolve: use of undeclared type `F64Trans` - --> $DIR/autodiff_illegal.rs:154:1 + --> $DIR/autodiff_illegal.rs:140:1 | -LL | #[autodiff(df18, Reverse, Active, Active)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `F64Trans` +LL | #[autodiff_reverse(df18, Active, Active)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `F64Trans` error[E0599]: the function or associated item `default` exists for tuple `(DoesNotImplDefault, DoesNotImplDefault)`, but its trait bounds were not satisfied - --> $DIR/autodiff_illegal.rs:181:1 + --> $DIR/autodiff_illegal.rs:167:1 | LL | struct DoesNotImplDefault; | ------------------------- doesn't satisfy `DoesNotImplDefault: Default` -LL | #[autodiff(df22, Forward, Dual)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item cannot be called on `(DoesNotImplDefault, DoesNotImplDefault)` due to unsatisfied trait bounds +LL | #[autodiff_forward(df22, Dual)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item cannot be called on `(DoesNotImplDefault, DoesNotImplDefault)` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `DoesNotImplDefault: Default` @@ -168,7 +153,7 @@ LL + #[derive(Default)] LL | struct DoesNotImplDefault; | -error: aborting due to 23 previous errors +error: aborting due to 21 previous errors Some errors have detailed explanations: E0428, E0433, E0599, E0658. For more information about an error, try `rustc --explain E0428`. diff --git a/tests/ui/autodiff/auxiliary/my_macro.rs b/tests/ui/autodiff/auxiliary/my_macro.rs index 217631a33c9..1d5a6de1454 100644 --- a/tests/ui/autodiff/auxiliary/my_macro.rs +++ b/tests/ui/autodiff/auxiliary/my_macro.rs @@ -3,6 +3,6 @@ use proc_macro::TokenStream; #[proc_macro_attribute] #[macro_use] -pub fn autodiff(_attr: TokenStream, item: TokenStream) -> TokenStream { +pub fn autodiff_forward(_attr: TokenStream, item: TokenStream) -> TokenStream { item // identity proc-macro } diff --git a/tests/ui/autodiff/visibility.rs b/tests/ui/autodiff/visibility.rs index dfaec03aef0..a84df75e799 100644 --- a/tests/ui/autodiff/visibility.rs +++ b/tests/ui/autodiff/visibility.rs @@ -6,12 +6,11 @@ #![feature(autodiff)] #[cfg(std_autodiff)] -use std::autodiff::autodiff; - +use std::autodiff::autodiff_forward; extern crate my_macro; -use my_macro::autodiff; // bring `autodiff` in scope +use my_macro::autodiff_forward; // bring `autodiff_forward` in scope -#[autodiff] -//[std_autodiff]~^^^ ERROR the name `autodiff` is defined multiple times +#[autodiff_forward(dfoo)] +//[std_autodiff]~^^^ ERROR the name `autodiff_forward` is defined multiple times //[std_autodiff]~^^ ERROR this rustc version does not support autodiff fn foo() {} diff --git a/tests/ui/autodiff/visibility.std_autodiff.stderr b/tests/ui/autodiff/visibility.std_autodiff.stderr index 720c9a00170..e45f1139012 100644 --- a/tests/ui/autodiff/visibility.std_autodiff.stderr +++ b/tests/ui/autodiff/visibility.std_autodiff.stderr @@ -1,23 +1,23 @@ -error[E0252]: the name `autodiff` is defined multiple times - --> $DIR/visibility.rs:12:5 +error[E0252]: the name `autodiff_forward` is defined multiple times + --> $DIR/visibility.rs:11:5 | -LL | use std::autodiff::autodiff; - | ----------------------- previous import of the macro `autodiff` here -... -LL | use my_macro::autodiff; // bring `autodiff` in scope - | ^^^^^^^^^^^^^^^^^^ `autodiff` reimported here +LL | use std::autodiff::autodiff_forward; + | ------------------------------- previous import of the macro `autodiff_forward` here +LL | extern crate my_macro; +LL | use my_macro::autodiff_forward; // bring `autodiff_forward` in scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `autodiff_forward` reimported here | - = note: `autodiff` must be defined only once in the macro namespace of this module + = note: `autodiff_forward` must be defined only once in the macro namespace of this module help: you can use `as` to change the binding name of the import | -LL | use my_macro::autodiff as other_autodiff; // bring `autodiff` in scope - | +++++++++++++++++ +LL | use my_macro::autodiff_forward as other_autodiff_forward; // bring `autodiff_forward` in scope + | +++++++++++++++++++++++++ error: this rustc version does not support autodiff - --> $DIR/visibility.rs:14:1 + --> $DIR/visibility.rs:13:1 | -LL | #[autodiff] - | ^^^^^^^^^^^ +LL | #[autodiff_forward(dfoo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr index 15ef257fbd8..e5edd8e45e6 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr @@ -1,8 +1,8 @@ error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:13:3 | -LL | #[autodiff(dfoo, Reverse)] - | ^^^^^^^^ +LL | #[autodiff_reverse(dfoo)] + | ^^^^^^^^^^^^^^^^ | = note: see issue #124509 for more information = help: add `#![feature(autodiff)]` to the crate attributes to enable @@ -11,8 +11,8 @@ LL | #[autodiff(dfoo, Reverse)] error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:9:5 | -LL | use std::autodiff::autodiff; - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | use std::autodiff::autodiff_reverse; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #124509 for more information = help: add `#![feature(autodiff)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr index f59e4955452..65ba033b358 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr @@ -1,8 +1,8 @@ error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:13:3 | -LL | #[autodiff(dfoo, Reverse)] - | ^^^^^^^^ +LL | #[autodiff_reverse(dfoo)] + | ^^^^^^^^^^^^^^^^ | = note: see issue #124509 for more information = help: add `#![feature(autodiff)]` to the crate attributes to enable @@ -11,14 +11,14 @@ LL | #[autodiff(dfoo, Reverse)] error: this rustc version does not support autodiff --> $DIR/feature-gate-autodiff-use.rs:13:1 | -LL | #[autodiff(dfoo, Reverse)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[autodiff_reverse(dfoo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:9:5 | -LL | use std::autodiff::autodiff; - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | use std::autodiff::autodiff_reverse; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #124509 for more information = help: add `#![feature(autodiff)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.rs b/tests/ui/feature-gates/feature-gate-autodiff-use.rs index 602e830b0b2..2864b786c12 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.rs +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.rs @@ -6,11 +6,11 @@ #![crate_type = "lib"] -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; //[has_support]~^ ERROR use of unstable library feature `autodiff` //[no_support]~^^ ERROR use of unstable library feature `autodiff` -#[autodiff(dfoo, Reverse)] +#[autodiff_reverse(dfoo)] //[has_support]~^ ERROR use of unstable library feature `autodiff` [E0658] //[no_support]~^^ ERROR use of unstable library feature `autodiff` [E0658] //[no_support]~| ERROR this rustc version does not support autodiff diff --git a/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr index c25cf7d3373..dcbaba71645 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr +++ b/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr @@ -1,12 +1,12 @@ -error: cannot find attribute `autodiff` in this scope +error: cannot find attribute `autodiff_reverse` in this scope --> $DIR/feature-gate-autodiff.rs:9:3 | -LL | #[autodiff(dfoo, Reverse)] - | ^^^^^^^^ +LL | #[autodiff_reverse(dfoo)] + | ^^^^^^^^^^^^^^^^ | help: consider importing this attribute macro | -LL + use std::autodiff::autodiff; +LL + use std::autodiff::autodiff_reverse; | error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr index c25cf7d3373..dcbaba71645 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr +++ b/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr @@ -1,12 +1,12 @@ -error: cannot find attribute `autodiff` in this scope +error: cannot find attribute `autodiff_reverse` in this scope --> $DIR/feature-gate-autodiff.rs:9:3 | -LL | #[autodiff(dfoo, Reverse)] - | ^^^^^^^^ +LL | #[autodiff_reverse(dfoo)] + | ^^^^^^^^^^^^^^^^ | help: consider importing this attribute macro | -LL + use std::autodiff::autodiff; +LL + use std::autodiff::autodiff_reverse; | error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-autodiff.rs b/tests/ui/feature-gates/feature-gate-autodiff.rs index 4249b229a69..adb35cb8e33 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff.rs +++ b/tests/ui/feature-gates/feature-gate-autodiff.rs @@ -6,7 +6,7 @@ // This checks that without the autodiff feature enabled, we can't use it. -#[autodiff(dfoo, Reverse)] -//[has_support]~^ ERROR cannot find attribute `autodiff` in this scope -//[no_support]~^^ ERROR cannot find attribute `autodiff` in this scope +#[autodiff_reverse(dfoo)] +//[has_support]~^ ERROR cannot find attribute `autodiff_reverse` in this scope +//[no_support]~^^ ERROR cannot find attribute `autodiff_reverse` in this scope fn foo() {} -- cgit 1.4.1-3-g733a5 From 8917ff602446372e45abed7ab3a58dc879638b1c Mon Sep 17 00:00:00 2001 From: Marcelo Domínguez Date: Tue, 20 May 2025 12:36:12 +0000 Subject: Update generic tests --- tests/codegen/autodiff/generic.rs | 4 ++-- tests/pretty/autodiff/autodiff_forward.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/codegen/autodiff/generic.rs b/tests/codegen/autodiff/generic.rs index 15e7d8a4957..2f674079be0 100644 --- a/tests/codegen/autodiff/generic.rs +++ b/tests/codegen/autodiff/generic.rs @@ -3,9 +3,9 @@ //@ needs-enzyme #![feature(autodiff)] -use std::autodiff::autodiff; +use std::autodiff::autodiff_reverse; -#[autodiff(d_square, Reverse, Duplicated, Active)] +#[autodiff_reverse(d_square, Duplicated, Active)] fn square + Copy>(x: &T) -> T { *x * *x } diff --git a/tests/pretty/autodiff/autodiff_forward.rs b/tests/pretty/autodiff/autodiff_forward.rs index 181b6ebc770..e23a1b3e241 100644 --- a/tests/pretty/autodiff/autodiff_forward.rs +++ b/tests/pretty/autodiff/autodiff_forward.rs @@ -64,7 +64,7 @@ pub fn f9() { } // Make sure we can handle generics -#[autodiff(d_square, Reverse, Duplicated, Active)] +#[autodiff_reverse(d_square, Duplicated, Active)] pub fn f10 + Copy>(x: &T) -> T { *x * *x } -- cgit 1.4.1-3-g733a5 From 226db317b1fcf13fc2cebea92855a30ff7877f32 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 21 May 2025 18:31:14 +0300 Subject: Correctly set the span of the proc_macro crate's Group delimiters Previously only the open delimiter's span was set, and this caused... weird problems. --- .../proc-macro-srv/src/server_impl/rust_analyzer_span.rs | 4 +++- .../crates/proc-macro-srv/src/server_impl/token_id.rs | 3 ++- .../crates/proc-macro-srv/src/server_impl/token_stream.rs | 11 +++++++++-- .../rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 64b40e7b943..e0c6e68f803 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -258,7 +258,9 @@ impl server::TokenStream for RaSpanServer { &mut self, stream: Self::TokenStream, ) -> Vec> { - stream.into_bridge() + stream.into_bridge(&mut |first, second| { + server::Span::join(self, first, second).unwrap_or(first) + }) } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs index 24a67bf45c8..d55b269f868 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -238,7 +238,8 @@ impl server::TokenStream for TokenIdServer { &mut self, stream: Self::TokenStream, ) -> Vec> { - stream.into_bridge() + // Can't join with `TokenId`. + stream.into_bridge(&mut |first, _second| first) } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs index 072557913c2..c5019a59172 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs @@ -56,7 +56,10 @@ impl TokenStream { self.token_trees.is_empty() } - pub(crate) fn into_bridge(self) -> Vec> { + pub(crate) fn into_bridge( + self, + join_spans: &mut dyn FnMut(S, S) -> S, + ) -> Vec> { let mut result = Vec::new(); let mut iter = self.token_trees.into_iter(); while let Some(tree) = iter.next() { @@ -98,7 +101,11 @@ impl TokenStream { token_trees: iter.by_ref().take(subtree.usize_len()).collect(), }) }, - span: bridge::DelimSpan::from_single(subtree.delimiter.open), + span: bridge::DelimSpan { + open: subtree.delimiter.open, + close: subtree.delimiter.close, + entire: join_spans(subtree.delimiter.open, subtree.delimiter.close), + }, })) } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index 3868fee40fb..3a6ce639d13 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -144,7 +144,7 @@ fn test_fn_like_macro_clone_ident_subtree() { SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT ident 42:2@0..5#ROOT2024 PUNCH , [alone] 42:2@5..6#ROOT2024 - SUBTREE [] 42:2@7..8#ROOT2024 42:2@7..8#ROOT2024"#]], + SUBTREE [] 42:2@7..9#ROOT2024 42:2@7..9#ROOT2024"#]], ); } -- cgit 1.4.1-3-g733a5 From 8acb1b5f0b3955f114677ee1725d39024202f16b Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 21 May 2025 09:47:29 -0400 Subject: internal: fix `integrated_benchmarks` to make actual edits --- .../rust-analyzer/src/integrated_benchmarks.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) 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 49ebffa909a..84b7888258f 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 @@ -147,7 +147,7 @@ fn integrated_completion_benchmark() { let _it = stdx::timeit("change"); let mut text = host.analysis().file_text(file_id).unwrap().to_string(); let completion_offset = - patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)") + patch(&mut text, "db.struct_signature(self.id)", "sel;\ndb.struct_signature(self.id)") + "sel".len(); let mut change = ChangeWithProcMacros::default(); change.change_file(file_id, Some(text)); @@ -197,9 +197,11 @@ fn integrated_completion_benchmark() { let completion_offset = { let _it = stdx::timeit("change"); let mut text = host.analysis().file_text(file_id).unwrap().to_string(); - let completion_offset = - patch(&mut text, "sel;\ndb.struct_data(self.id)", ";sel;\ndb.struct_data(self.id)") - + ";sel".len(); + let completion_offset = patch( + &mut text, + "sel;\ndb.struct_signature(self.id)", + ";sel;\ndb.struct_signature(self.id)", + ) + ";sel".len(); let mut change = ChangeWithProcMacros::default(); change.change_file(file_id, Some(text)); host.apply_change(change); @@ -247,9 +249,11 @@ fn integrated_completion_benchmark() { let completion_offset = { let _it = stdx::timeit("change"); let mut text = host.analysis().file_text(file_id).unwrap().to_string(); - let completion_offset = - patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)") - + "self.".len(); + let completion_offset = patch( + &mut text, + "sel;\ndb.struct_signature(self.id)", + "self.;\ndb.struct_signature(self.id)", + ) + "self.".len(); let mut change = ChangeWithProcMacros::default(); change.change_file(file_id, Some(text)); host.apply_change(change); @@ -366,7 +370,7 @@ fn integrated_diagnostics_benchmark() { { let _it = stdx::timeit("change"); let mut text = host.analysis().file_text(file_id).unwrap().to_string(); - patch(&mut text, "db.struct_data(self.id)", "();\ndb.struct_data(self.id)"); + patch(&mut text, "db.struct_signature(self.id)", "();\ndb.struct_signature(self.id)"); let mut change = ChangeWithProcMacros::default(); change.change_file(file_id, Some(text)); host.apply_change(change); -- cgit 1.4.1-3-g733a5 From 24a416cc5714ab7129fa91f4e94f6dd877675b05 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 22 May 2025 07:55:06 +0200 Subject: Support `transmute_unchecked` intrinsic for mir-eval --- src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 7cf948b178e..90c52ee96f1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -1121,7 +1121,7 @@ impl Evaluator<'_> { // We don't call any drop glue yet, so there is nothing here Ok(()) } - "transmute" => { + "transmute" | "transmute_unchecked" => { let [arg] = args else { return Err(MirEvalError::InternalError( "transmute arg is not provided".into(), -- cgit 1.4.1-3-g733a5 From fb181cf6603ebe56a9cc39b9a1bcbc39a226f190 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 22 May 2025 07:35:59 +0000 Subject: Remove rust-analyzer.vs from other editors --- .../rust-analyzer/docs/book/src/other_editors.md | 24 ---------------------- 1 file changed, 24 deletions(-) diff --git a/src/tools/rust-analyzer/docs/book/src/other_editors.md b/src/tools/rust-analyzer/docs/book/src/other_editors.md index 1eac7dd2c25..896df52af5f 100644 --- a/src/tools/rust-analyzer/docs/book/src/other_editors.md +++ b/src/tools/rust-analyzer/docs/book/src/other_editors.md @@ -364,30 +364,6 @@ binary](./rust_analyzer_binary.html). There are multiple rust-analyzer extensions for Visual Studio 2022 on Windows: -### rust-analyzer.vs - -(License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 -International) - -[Visual Studio -Marketplace](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer) - -[GitHub](https://github.com/kitamstudios/rust-analyzer/) - -Support for Rust development in the Visual Studio IDE is enabled by the -[rust-analyzer](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer) -package. Either click on the download link or install from IDE’s -extension manager. For now [Visual Studio -2022](https://visualstudio.microsoft.com/downloads/) is required. All -editions are supported viz. Community, Professional & Enterprise. The -package aims to provide 0-friction installation and therefore comes -loaded with most things required including rust-analyzer binary. If -anything it needs is missing, appropriate errors / warnings will guide -the user. E.g. cargo.exe needs to be in path and the package will tell -you as much. This package is under rapid active development. So if you -encounter any issues please file it at -[rust-analyzer.vs](https://github.com/kitamstudios/rust-analyzer/). - ### VS RustAnalyzer (License: GPL) -- cgit 1.4.1-3-g733a5 From f0096aea4020b354415268539cb4fddf6fc5f48d Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Fri, 23 May 2025 01:01:21 +0300 Subject: Normalize when checking for uninhabited types for pattern exhaustiveness checking --- .../crates/hir-ty/src/diagnostics/expr.rs | 10 +++++---- .../src/diagnostics/match_check/pat_analysis.rs | 24 +++++++++++++++------ .../crates/hir-ty/src/inhabitedness.rs | 23 ++++++++++++++++---- .../rust-analyzer/crates/hir-ty/src/mir/lower.rs | 24 +++++++++++---------- .../src/handlers/non_exhaustive_let.rs | 25 ++++++++++++++++++++++ 5 files changed, 81 insertions(+), 25 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index e4a23cbbacf..8665e9d33fc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -25,7 +25,7 @@ use triomphe::Arc; use typed_arena::Arena; use crate::{ - Adjust, InferenceResult, Interner, Ty, TyExt, TyKind, + Adjust, InferenceResult, Interner, TraitEnvironment, Ty, TyExt, TyKind, db::HirDatabase, diagnostics::match_check::{ self, @@ -74,8 +74,9 @@ impl BodyValidationDiagnostic { let _p = tracing::info_span!("BodyValidationDiagnostic::collect").entered(); let infer = db.infer(owner); let body = db.body(owner); + let env = db.trait_environment_for_body(owner); let mut validator = - ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints }; + ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints, env }; validator.validate_body(db); validator.diagnostics } @@ -85,6 +86,7 @@ struct ExprValidator { owner: DefWithBodyId, body: Arc, infer: Arc, + env: Arc, diagnostics: Vec, validate_lints: bool, } @@ -190,7 +192,7 @@ impl ExprValidator { return; } - let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db); + let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db, self.env.clone()); let pattern_arena = Arena::new(); let mut m_arms = Vec::with_capacity(arms.len()); @@ -317,7 +319,7 @@ impl ExprValidator { return; }; let pattern_arena = Arena::new(); - let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db); + let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db, self.env.clone()); for stmt in &**statements { let &Statement::Let { pat, initializer, else_branch: None, .. } = stmt else { continue; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 785277d70c6..dd82a0f45ca 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -12,9 +12,10 @@ use rustc_pattern_analysis::{ }; use smallvec::{SmallVec, smallvec}; use stdx::never; +use triomphe::Arc; use crate::{ - AdtId, Interner, Scalar, Ty, TyExt, TyKind, + AdtId, Interner, Scalar, TraitEnvironment, Ty, TyExt, TyKind, db::HirDatabase, infer::normalize, inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from}, @@ -69,13 +70,19 @@ pub(crate) struct MatchCheckCtx<'db> { body: DefWithBodyId, pub(crate) db: &'db dyn HirDatabase, exhaustive_patterns: bool, + env: Arc, } impl<'db> MatchCheckCtx<'db> { - pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'db dyn HirDatabase) -> Self { + pub(crate) fn new( + module: ModuleId, + body: DefWithBodyId, + db: &'db dyn HirDatabase, + env: Arc, + ) -> Self { let def_map = module.crate_def_map(db); let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns); - Self { module, body, db, exhaustive_patterns } + Self { module, body, db, exhaustive_patterns, env } } pub(crate) fn compute_match_usefulness( @@ -100,7 +107,7 @@ impl<'db> MatchCheckCtx<'db> { } fn is_uninhabited(&self, ty: &Ty) -> bool { - is_ty_uninhabited_from(self.db, ty, self.module) + is_ty_uninhabited_from(self.db, ty, self.module, self.env.clone()) } /// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`. @@ -459,8 +466,13 @@ impl PatCx for MatchCheckCtx<'_> { } else { let mut variants = IndexVec::with_capacity(enum_data.variants.len()); for &(variant, _) in enum_data.variants.iter() { - let is_uninhabited = - is_enum_variant_uninhabited_from(cx.db, variant, subst, cx.module); + let is_uninhabited = is_enum_variant_uninhabited_from( + cx.db, + variant, + subst, + cx.module, + self.env.clone(), + ); let visibility = if is_uninhabited { VariantVisibility::Empty } else { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs index e0c3279d3fb..e81a5e3c311 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs @@ -7,17 +7,24 @@ use chalk_ir::{ }; use hir_def::{AdtId, EnumVariantId, ModuleId, VariantId, visibility::Visibility}; use rustc_hash::FxHashSet; +use triomphe::Arc; use crate::{ - Binders, Interner, Substitution, Ty, TyKind, consteval::try_const_usize, db::HirDatabase, + AliasTy, Binders, Interner, Substitution, TraitEnvironment, Ty, TyKind, + consteval::try_const_usize, db::HirDatabase, }; // FIXME: Turn this into a query, it can be quite slow /// Checks whether a type is visibly uninhabited from a particular module. -pub(crate) fn is_ty_uninhabited_from(db: &dyn HirDatabase, ty: &Ty, target_mod: ModuleId) -> bool { +pub(crate) fn is_ty_uninhabited_from( + db: &dyn HirDatabase, + ty: &Ty, + target_mod: ModuleId, + env: Arc, +) -> bool { let _p = tracing::info_span!("is_ty_uninhabited_from", ?ty).entered(); let mut uninhabited_from = - UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() }; + UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default(), env }; let inhabitedness = ty.visit_with(&mut uninhabited_from, DebruijnIndex::INNERMOST); inhabitedness == BREAK_VISIBLY_UNINHABITED } @@ -29,11 +36,12 @@ pub(crate) fn is_enum_variant_uninhabited_from( variant: EnumVariantId, subst: &Substitution, target_mod: ModuleId, + env: Arc, ) -> bool { let _p = tracing::info_span!("is_enum_variant_uninhabited_from").entered(); let mut uninhabited_from = - UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() }; + UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default(), env }; let inhabitedness = uninhabited_from.visit_variant(variant.into(), subst); inhabitedness == BREAK_VISIBLY_UNINHABITED } @@ -44,6 +52,7 @@ struct UninhabitedFrom<'a> { // guard for preventing stack overflow in non trivial non terminating types max_depth: usize, db: &'a dyn HirDatabase, + env: Arc, } const CONTINUE_OPAQUELY_INHABITED: ControlFlow = Continue(()); @@ -78,6 +87,12 @@ impl TypeVisitor for UninhabitedFrom<'_> { Some(0) | None => CONTINUE_OPAQUELY_INHABITED, Some(1..) => item_ty.super_visit_with(self, outer_binder), }, + TyKind::Alias(AliasTy::Projection(projection)) => { + // FIXME: I think this currently isn't used for monomorphized bodies, so there is no need to handle + // `TyKind::AssociatedType`, but perhaps in the future it will. + let normalized = self.db.normalize_projection(projection.clone(), self.env.clone()); + self.visit_ty(&normalized, outer_binder) + } _ => CONTINUE_OPAQUELY_INHABITED, }; self.recursive_ty.remove(ty); 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 7fcc89e5183..e6caf2d8d97 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 @@ -25,7 +25,7 @@ use syntax::TextRange; use triomphe::Arc; use crate::{ - Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt, + Adjust, Adjustment, AutoBorrow, CallableDefId, TraitEnvironment, TyBuilder, TyExt, consteval::ConstEvalError, db::{HirDatabase, InternedClosure, InternedClosureId}, display::{DisplayTarget, HirDisplay, hir_display_with_store}, @@ -79,6 +79,7 @@ struct MirLowerCtx<'db> { infer: &'db InferenceResult, resolver: Resolver<'db>, drop_scopes: Vec, + env: Arc, } // FIXME: Make this smaller, its stored in database queries @@ -288,6 +289,7 @@ impl<'ctx> MirLowerCtx<'ctx> { closures: vec![], }; let resolver = owner.resolver(db); + let env = db.trait_environment_for_body(owner); MirLowerCtx { result: mir, @@ -300,6 +302,7 @@ impl<'ctx> MirLowerCtx<'ctx> { labeled_loop_blocks: Default::default(), discr_temp: None, drop_scopes: vec![DropScope::default()], + env, } } @@ -944,10 +947,7 @@ impl<'ctx> MirLowerCtx<'ctx> { 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), - ); + let mut table = InferenceTable::new(self.db, self.env.clone()); cast_kind(&mut table, &source_ty, &target_ty)? }; @@ -1412,11 +1412,8 @@ impl<'ctx> MirLowerCtx<'ctx> { } fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result { - let size = || { - self.db - .layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner)) - .map(|it| it.size.bytes_usize()) - }; + let size = + || self.db.layout_of_ty(ty.clone(), self.env.clone()).map(|it| it.size.bytes_usize()); const USIZE_SIZE: usize = size_of::(); let bytes: Box<[_]> = match l { hir_def::hir::Literal::String(b) => { @@ -1723,7 +1720,12 @@ impl<'ctx> MirLowerCtx<'ctx> { } fn is_uninhabited(&self, expr_id: ExprId) -> bool { - is_ty_uninhabited_from(self.db, &self.infer[expr_id], self.owner.module(self.db)) + is_ty_uninhabited_from( + self.db, + &self.infer[expr_id], + self.owner.module(self.db), + self.env.clone(), + ) } /// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs index 35cefd23975..f20b6dea122 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs @@ -106,4 +106,29 @@ fn test(x: Result) { "#, ); } + + #[test] + fn empty_patterns_normalize() { + check_diagnostics( + r#" +enum Infallible {} + +trait Foo { + type Assoc; +} +enum Enum { + A, + B(T::Assoc), +} + +impl Foo for () { + type Assoc = Infallible; +} + +fn foo(v: Enum<()>) { + let Enum::A = v; +} + "#, + ); + } } -- cgit 1.4.1-3-g733a5 From 69ba323c1ca1faba14ace7cec19dd5b738367960 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 23 May 2025 12:57:07 +0200 Subject: Bump salsa --- src/tools/rust-analyzer/Cargo.lock | 241 ++------------------- src/tools/rust-analyzer/Cargo.toml | 7 +- .../rust-analyzer/crates/base-db/src/input.rs | 12 +- src/tools/rust-analyzer/crates/base-db/src/lib.rs | 4 +- .../rust-analyzer/crates/hir-def/src/lang_item.rs | 2 +- .../rust-analyzer/crates/hir-def/src/nameres.rs | 8 +- .../rust-analyzer/crates/hir-def/src/test_db.rs | 23 +- .../rust-analyzer/crates/hir-ty/src/test_db.rs | 22 +- src/tools/rust-analyzer/crates/ide-db/src/lib.rs | 4 +- .../crates/query-group-macro/tests/logger_db.rs | 40 ++-- 10 files changed, 83 insertions(+), 280 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index bd8146defae..01de430925d 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -17,15 +17,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - [[package]] name = "allocator-api2" version = "0.2.21" @@ -124,12 +115,9 @@ dependencies = [ [[package]] name = "boxcar" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6740c6e2fc6360fa57c35214c7493826aee95993926092606f27c983b40837be" -dependencies = [ - "loom", -] +checksum = "66bb12751a83493ef4b8da1120451a262554e216a247f14b48cb5e8fe7ed8bdf" [[package]] name = "camino" @@ -511,19 +499,6 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" -[[package]] -name = "generator" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" -dependencies = [ - "cfg-if", - "libc", - "log", - "rustversion", - "windows 0.58.0", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -1213,19 +1188,6 @@ version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - [[package]] name = "lsp-server" version = "0.7.8" @@ -1265,15 +1227,6 @@ dependencies = [ "url", ] -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - [[package]] name = "mbe" version = "0.0.0" @@ -1400,16 +1353,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.50.1" @@ -1471,12 +1414,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "parking_lot" version = "0.12.3" @@ -1648,7 +1585,7 @@ dependencies = [ "indexmap", "nix", "tracing", - "windows 0.61.1", + "windows", ] [[package]] @@ -1864,50 +1801,6 @@ dependencies = [ "thiserror 2.0.12", ] -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - [[package]] name = "rowan" version = "0.15.15" @@ -2026,12 +1919,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "rustversion" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" - [[package]] name = "ryu" version = "1.0.20" @@ -2040,9 +1927,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f80d5cf3c3fcab2cef898012f242a670477a1baa609267376af9cb4409026c5" +checksum = "c8fff508e3d6ef42a32607f7538e17171a877a12015e32036f46e99d00c95781" dependencies = [ "boxcar", "crossbeam-queue", @@ -2063,15 +1950,15 @@ dependencies = [ [[package]] name = "salsa-macro-rules" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05303d72606fbf2b9c9523cda2039bb8ecb00304027a3cd7e52b02a65c7d9185" +checksum = "8ea72b3c06f2ce6350fe3a0eeb7aaaf842d1d8352b706973c19c4f02e298a87c" [[package]] name = "salsa-macros" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2f0e2a30c65cb3cd63440c491dde68d9af7e1be2b77832ac7057141107db50" +checksum = "0ce92025bc160b27814a207cb78d680973af17f863c7f4fc56cf3a535e22f378" dependencies = [ "heck", "proc-macro2", @@ -2556,15 +2443,9 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ - "matchers", - "nu-ansi-term 0.46.0", - "once_cell", - "regex", "sharded-slab", - "smallvec", "thread_local", "time", - "tracing", "tracing-core", "tracing-log", ] @@ -2575,7 +2456,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f459ca79f1b0d5f71c54ddfde6debfc59c8b6eeb46808ae492077f739dc7b49c" dependencies = [ - "nu-ansi-term 0.50.1", + "nu-ansi-term", "tracing-core", "tracing-log", "tracing-subscriber", @@ -2709,22 +2590,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.9" @@ -2734,22 +2599,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -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" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.61.1" @@ -2757,7 +2606,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" dependencies = [ "windows-collections", - "windows-core 0.61.0", + "windows-core", "windows-future", "windows-link", "windows-numerics", @@ -2769,20 +2618,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core 0.61.0", -] - -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", + "windows-core", ] [[package]] @@ -2791,11 +2627,11 @@ version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ - "windows-implement 0.60.0", - "windows-interface 0.59.1", + "windows-implement", + "windows-interface", "windows-link", - "windows-result 0.3.2", - "windows-strings 0.4.0", + "windows-result", + "windows-strings", ] [[package]] @@ -2804,21 +2640,10 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32" dependencies = [ - "windows-core 0.61.0", + "windows-core", "windows-link", ] -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-implement" version = "0.60.0" @@ -2830,17 +2655,6 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-interface" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-interface" version = "0.59.1" @@ -2864,19 +2678,10 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core 0.61.0", + "windows-core", "windows-link", ] -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-result" version = "0.3.2" @@ -2886,16 +2691,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows-strings" version = "0.4.0" diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 07731bae3f3..8c507189846 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -132,11 +132,8 @@ pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.6", default-features = false } rayon = "1.10.0" rowan = "=0.15.15" -salsa = { version = "0.21.1", default-features = false, features = [ - "rayon", - "salsa_unstable", -] } -salsa-macros = "0.21.1" +salsa = { version = "0.22.0", default-features = false, features = ["rayon","salsa_unstable"] } +salsa-macros = "0.22.0" semver = "1.0.26" serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } 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 d42d7e5707d..745238167bc 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -395,21 +395,21 @@ impl BuiltDependency { pub type CratesIdMap = FxHashMap; #[salsa_macros::input] -#[derive(Debug)] +#[derive(Debug, PartialOrd, Ord)] pub struct Crate { - #[return_ref] + #[returns(ref)] pub data: BuiltCrateData, /// Crate data that is not needed for analysis. /// /// This is split into a separate field to increase incrementality. - #[return_ref] + #[returns(ref)] pub extra_data: ExtraCrateData, // This is in `Arc` because it is shared for all crates in a workspace. - #[return_ref] + #[returns(ref)] pub workspace_data: Arc, - #[return_ref] + #[returns(ref)] pub cfg_options: CfgOptions, - #[return_ref] + #[returns(ref)] pub env: Env, } diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index a67fbf75c02..4d4e6cae037 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -32,6 +32,7 @@ pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet} macro_rules! impl_intern_key { ($id:ident, $loc:ident) => { #[salsa_macros::interned(no_lifetime)] + #[derive(PartialOrd, Ord)] pub struct $id { pub loc: $loc, } @@ -165,6 +166,7 @@ impl Files { } #[salsa_macros::interned(no_lifetime, debug, constructor=from_span)] +#[derive(PartialOrd, Ord)] pub struct EditionedFileId { pub editioned_file_id: span::EditionedFileId, } @@ -356,7 +358,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse Option<&[SyntaxError]> { - #[salsa_macros::tracked(return_ref)] + #[salsa_macros::tracked(returns(ref))] fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option> { let errors = db.parse(file_id).errors(); match &*errors { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 59344641f47..4ad44775ea1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -85,7 +85,7 @@ impl LangItemTarget { } /// Salsa query. This will look for lang items in a specific crate. -#[salsa_macros::tracked(return_ref)] +#[salsa_macros::tracked(returns(ref))] pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option> { let _p = tracing::info_span!("crate_lang_items_query").entered(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index d4b30a1d3e6..f337f83156a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -381,15 +381,15 @@ mod __ { #[salsa_macros::tracked] pub(crate) struct DefMapPair<'db> { #[tracked] - #[return_ref] + #[returns(ref)] pub(crate) def_map: DefMap, - #[return_ref] + #[returns(ref)] pub(crate) local: LocalDefMap, } } pub(crate) use __::DefMapPair; -#[salsa_macros::tracked(return_ref)] +#[salsa_macros::tracked(returns(ref))] pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefMapPair<'_> { let krate = crate_id.data(db); let _p = tracing::info_span!( @@ -420,7 +420,7 @@ pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefM DefMapPair::new(db, def_map, local_def_map) } -#[salsa_macros::tracked(return_ref)] +#[salsa_macros::tracked(returns(ref))] pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap { let BlockLoc { ast_id, module } = block_id.lookup(db); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs index 6c995ab6c23..e30a5b65a1f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs @@ -30,9 +30,18 @@ pub(crate) struct TestDB { impl Default for TestDB { fn default() -> Self { + let events = >>>>::default(); let mut this = Self { - storage: Default::default(), - events: Default::default(), + storage: salsa::Storage::new(Some(Box::new({ + let events = events.clone(); + move |event| { + let mut events = events.lock().unwrap(); + if let Some(events) = &mut *events { + events.push(event); + } + } + }))), + events, files: Default::default(), crates_map: Default::default(), }; @@ -45,15 +54,7 @@ impl Default for TestDB { } #[salsa_macros::db] -impl salsa::Database for TestDB { - fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) { - let mut events = self.events.lock().unwrap(); - if let Some(events) = &mut *events { - let event = event(); - events.push(event); - } - } -} +impl salsa::Database for TestDB {} impl fmt::Debug for TestDB { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs index 8f0d17c9dc4..d049c678e2d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs @@ -27,9 +27,18 @@ pub(crate) struct TestDB { impl Default for TestDB { fn default() -> Self { + let events = >>>>::default(); let mut this = Self { - storage: Default::default(), - events: Default::default(), + storage: salsa::Storage::new(Some(Box::new({ + let events = events.clone(); + move |event| { + let mut events = events.lock().unwrap(); + if let Some(events) = &mut *events { + events.push(event); + } + } + }))), + events, files: Default::default(), crates_map: Default::default(), }; @@ -103,14 +112,7 @@ impl SourceDatabase for TestDB { } #[salsa_macros::db] -impl salsa::Database for TestDB { - fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) { - let mut events = self.events.lock().unwrap(); - if let Some(events) = &mut *events { - events.push(event()); - } - } -} +impl salsa::Database for TestDB {} impl panic::RefUnwindSafe for TestDB {} 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 63cc7cde280..c94be7e164e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -92,9 +92,7 @@ pub struct RootDatabase { impl std::panic::RefUnwindSafe for RootDatabase {} #[salsa_macros::db] -impl salsa::Database for RootDatabase { - fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {} -} +impl salsa::Database for RootDatabase {} impl Drop for RootDatabase { fn drop(&mut self) { diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs index bade0c2cd6f..71af63a0d3b 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs @@ -1,33 +1,41 @@ use std::sync::{Arc, Mutex}; #[salsa_macros::db] -#[derive(Default, Clone)] +#[derive(Clone)] pub(crate) struct LoggerDb { storage: salsa::Storage, logger: Logger, } +impl Default for LoggerDb { + fn default() -> Self { + let logger = Logger::default(); + Self { + storage: salsa::Storage::new(Some(Box::new({ + let logger = logger.clone(); + move |event| match event.kind { + salsa::EventKind::WillExecute { .. } + | salsa::EventKind::WillCheckCancellation + | salsa::EventKind::DidValidateMemoizedValue { .. } + | salsa::EventKind::WillDiscardStaleOutput { .. } + | salsa::EventKind::DidDiscard { .. } => { + logger.logs.lock().unwrap().push(format!("salsa_event({:?})", event.kind)); + } + _ => {} + } + }))), + logger, + } + } +} + #[derive(Default, Clone)] struct Logger { logs: Arc>>, } #[salsa_macros::db] -impl salsa::Database for LoggerDb { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { - let event = event(); - match event.kind { - salsa::EventKind::WillExecute { .. } - | salsa::EventKind::WillCheckCancellation - | salsa::EventKind::DidValidateMemoizedValue { .. } - | salsa::EventKind::WillDiscardStaleOutput { .. } - | salsa::EventKind::DidDiscard { .. } => { - self.push_log(format!("salsa_event({:?})", event.kind)); - } - _ => {} - } - } -} +impl salsa::Database for LoggerDb {} impl LoggerDb { /// Log an event from inside a tracked function. -- cgit 1.4.1-3-g733a5 From 947be5f4316088f44cf2db69d137fd9afbfd7723 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 17 Apr 2025 19:43:56 -0400 Subject: add CStr::display The implementation delegates to `::fmt`. Link: https://github.com/rust-lang/libs-team/issues/550 Link: https://github.com/rust-lang/rust/issues/139984. --- library/core/src/ffi/c_str.rs | 24 ++++++++++++++++++++++++ library/coretests/tests/ffi/cstr.rs | 6 ++++++ library/coretests/tests/lib.rs | 1 + 3 files changed, 31 insertions(+) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index ac07c645c01..c2799fa0b5c 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -659,6 +659,30 @@ impl CStr { // instead of doing it afterwards. str::from_utf8(self.to_bytes()) } + + /// Returns an object that implements [`Display`] for safely printing a [`CStr`] that may + /// contain non-Unicode data. + /// + /// Behaves as if `self` were first lossily converted to a `str`, with invalid UTF-8 presented + /// as the Unicode replacement character: �. + /// + /// [`Display`]: fmt::Display + /// + /// # Examples + /// + /// ``` + /// #![feature(cstr_display)] + /// + /// let cstr = c"Hello, world!"; + /// println!("{}", cstr.display()); + /// ``` + #[unstable(feature = "cstr_display", issue = "139984")] + #[must_use = "this does not display the `CStr`; \ + it returns an object that can be displayed"] + #[inline] + pub fn display(&self) -> impl fmt::Display { + crate::bstr::ByteStr::from_bytes(self.to_bytes()) + } } // `.to_bytes()` representations are compared instead of the inner `[c_char]`s, diff --git a/library/coretests/tests/ffi/cstr.rs b/library/coretests/tests/ffi/cstr.rs index 0d85b22c585..dc34240cd99 100644 --- a/library/coretests/tests/ffi/cstr.rs +++ b/library/coretests/tests/ffi/cstr.rs @@ -19,3 +19,9 @@ fn debug() { let s = c"abc\x01\x02\n\xE2\x80\xA6\xFF"; assert_eq!(format!("{s:?}"), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#); } + +#[test] +fn display() { + let s = c"\xf0\x28\x8c\xbc"; + assert_eq!(format!("{}", s.display()), "�(��"); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index b1301200981..693b14ef762 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -23,6 +23,7 @@ #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] +#![feature(cstr_display)] #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] -- cgit 1.4.1-3-g733a5 From a3bd12b88aaf32b1036cdcb2ef3efe509dbebc15 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 24 May 2025 22:12:15 +0200 Subject: Path::with_extension: improve examples --- library/std/src/path.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 7959c633858..0583ee1eb32 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2743,12 +2743,27 @@ impl Path { /// /// let path = Path::new("foo.rs"); /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt")); + /// assert_eq!(path.with_extension(""), PathBuf::from("foo")); + /// ``` + /// + /// Handling multiple extensions: + /// + /// ``` + /// use std::path::{Path, PathBuf}; /// /// let path = Path::new("foo.tar.gz"); - /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar")); /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz")); /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt")); /// ``` + /// + /// Adding an extension where one did not exist: + /// + /// ``` + /// use std::path::{Path, PathBuf}; + /// + /// let path = Path::new("foo"); + /// assert_eq!(path.with_extension("rs"), PathBuf::from("foo.rs")); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_extension>(&self, extension: S) -> PathBuf { self._with_extension(extension.as_ref()) -- cgit 1.4.1-3-g733a5 From 248f4b2ad2b18ab322748cc62b3524c109206b98 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 24 May 2025 22:17:55 +0200 Subject: reduce clutter... too many imports --- library/std/src/path.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 0583ee1eb32..87c5d6f0438 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2739,30 +2739,30 @@ impl Path { /// # Examples /// /// ``` - /// use std::path::{Path, PathBuf}; + /// use std::path::Path; /// /// let path = Path::new("foo.rs"); - /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt")); - /// assert_eq!(path.with_extension(""), PathBuf::from("foo")); + /// assert_eq!(path.with_extension("txt"), Path::new("foo.txt")); + /// assert_eq!(path.with_extension(""), Path::new("foo")); /// ``` /// /// Handling multiple extensions: /// /// ``` - /// use std::path::{Path, PathBuf}; + /// use std::path::Path; /// /// let path = Path::new("foo.tar.gz"); - /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz")); - /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt")); + /// assert_eq!(path.with_extension("xz"), Path::new("foo.tar.xz")); + /// assert_eq!(path.with_extension("").with_extension("txt"), Path::new("foo.txt")); /// ``` /// /// Adding an extension where one did not exist: /// /// ``` - /// use std::path::{Path, PathBuf}; + /// use std::path::Path; /// /// let path = Path::new("foo"); - /// assert_eq!(path.with_extension("rs"), PathBuf::from("foo.rs")); + /// assert_eq!(path.with_extension("rs"), Path::new("foo.rs")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_extension>(&self, extension: S) -> PathBuf { -- cgit 1.4.1-3-g733a5 From fe1808718cc83aab514a92c7129fe76e122045cf Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 25 May 2025 17:20:20 +0300 Subject: Fix IDE resolution of item macros It wasn't inside the source, because there was no source map. --- src/tools/rust-analyzer/crates/hir-def/src/db.rs | 3 ++ .../rust-analyzer/crates/hir-def/src/resolver.rs | 9 +++++ .../rust-analyzer/crates/hir-expand/src/lib.rs | 2 ++ .../rust-analyzer/crates/hir/src/semantics.rs | 10 +++--- .../crates/hir/src/source_analyzer.rs | 41 ++++++++++------------ .../crates/ide-completion/src/tests/item.rs | 38 +++++++++++++++++++- 6 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 4a9a3b12cfa..6f9340a0e4d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -422,6 +422,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, + block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), local_inner: false, allow_internal_unsafe: loc.allow_internal_unsafe, @@ -435,6 +436,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, + block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), allow_internal_unsafe: loc @@ -450,6 +452,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, + block: None, kind: MacroDefKind::ProcMacro( InFile::new(loc.id.file_id(), makro.ast_id), loc.expander, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 16988ddf04b..416bcbb096b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -696,6 +696,15 @@ impl<'db> Resolver<'db> { &def_map[local_id].scope } + pub fn item_scopes(&self) -> impl Iterator { + self.scopes() + .filter_map(move |scope| match scope { + Scope::BlockScope(m) => Some(&m.def_map[m.module_id].scope), + _ => None, + }) + .chain(std::iter::once(&self.module_scope.def_map[self.module_scope.module_id].scope)) + } + pub fn krate(&self) -> Crate { self.module_scope.def_map.krate() } 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 d844d8f41ee..19cd0298e93 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -258,6 +258,8 @@ pub struct MacroCallLoc { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { pub krate: Crate, + // FIXME: In `hir-expand` we can't refer to `BlockId`. + pub block: Option, pub edition: Edition, pub kind: MacroDefKind, pub local_inner: bool, diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index caa6700de9f..e479770b47e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -411,7 +411,7 @@ impl<'db> SemanticsImpl<'db> { let sa = self.analyze_no_infer(macro_call.syntax())?; let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = sa.expand(self.db, macro_call)?; + let file_id = sa.expansion(self.db, macro_call)?; let node = self.parse_or_expand(file_id.into()); Some(node) @@ -437,7 +437,7 @@ impl<'db> SemanticsImpl<'db> { let sa = self.analyze_no_infer(macro_call.syntax())?; let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = sa.expand(self.db, macro_call)?; + let file_id = sa.expansion(self.db, macro_call)?; let macro_call = self.db.lookup_intern_macro_call(file_id); let skip = matches!( @@ -576,7 +576,7 @@ impl<'db> SemanticsImpl<'db> { ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { let analyzer = self.analyze_no_infer(actual_macro_call.syntax())?; let macro_call = InFile::new(analyzer.file_id, actual_macro_call); - let macro_file = analyzer.expansion(macro_call)?; + let macro_file = analyzer.expansion(self.db, macro_call)?; hir_expand::db::expand_speculative( self.db, macro_file, @@ -1120,7 +1120,7 @@ impl<'db> SemanticsImpl<'db> { false, ) })? - .expand(self.db, mcall.as_ref())?; + .expansion(self.db, mcall.as_ref())?; m_cache.insert(mcall, it); it } @@ -1579,7 +1579,7 @@ impl<'db> SemanticsImpl<'db> { let sa = self.analyze(macro_call.syntax())?; self.db .parse_macro_expansion( - sa.expand(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?, + sa.expansion(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?, ) .value .1 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 ea21546f9d7..be581292152 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -26,7 +26,7 @@ use hir_def::{ }, hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lang_item::LangItem, - nameres::{MacroSubNs, crate_def_map}, + nameres::{MacroSubNs, block_def_map, crate_def_map}, resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope}, type_ref::{Mutability, TypeRefId}, }; @@ -218,8 +218,16 @@ impl<'db> SourceAnalyzer<'db> { }) } - pub(crate) fn expansion(&self, node: InFile<&ast::MacroCall>) -> Option { - self.store_sm()?.expansion(node) + pub(crate) fn expansion( + &self, + db: &dyn HirDatabase, + macro_call: InFile<&ast::MacroCall>, + ) -> Option { + self.store_sm().and_then(|sm| sm.expansion(macro_call)).or_else(|| { + let ast_id_map = db.ast_id_map(macro_call.file_id); + let call_ast_id = macro_call.with_value(ast_id_map.ast_id(macro_call.value)); + self.resolver.item_scopes().find_map(|scope| scope.macro_invoc(call_ast_id)) + }) } fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc { @@ -747,17 +755,16 @@ impl<'db> SourceAnalyzer<'db> { pub(crate) fn resolve_macro_call( &self, - db: &'db dyn HirDatabase, + db: &dyn HirDatabase, macro_call: InFile<&ast::MacroCall>, ) -> Option { - let bs = self.store_sm()?; - bs.expansion(macro_call).and_then(|it| { - // FIXME: Block def maps + self.expansion(db, macro_call).and_then(|it| { let def = it.lookup(db).def; - crate_def_map(db, def.krate) - .macro_def_to_macro_id - .get(&def.kind.erased_ast_id()) - .map(|it| (*it).into()) + let def_map = match def.block { + Some(block) => block_def_map(db, base_db::salsa::plumbing::FromId::from_id(block)), + None => crate_def_map(db, def.krate), + }; + def_map.macro_def_to_macro_id.get(&def.kind.erased_ast_id()).map(|it| (*it).into()) }) } @@ -1292,18 +1299,6 @@ impl<'db> SourceAnalyzer<'db> { .collect() } - pub(crate) fn expand( - &self, - db: &'db dyn HirDatabase, - macro_call: InFile<&ast::MacroCall>, - ) -> Option { - self.store_sm().and_then(|bs| bs.expansion(macro_call)).or_else(|| { - self.resolver.item_scope().macro_invoc( - macro_call.with_value(db.ast_id_map(macro_call.file_id).ast_id(macro_call.value)), - ) - }) - } - pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option { let infer = self.infer()?; let expr_id = self.expr_id(record_lit.into())?; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs index 55689034fb4..ed87b339fed 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs @@ -4,7 +4,7 @@ //! in [crate::completions::mod_]. use expect_test::expect; -use crate::tests::{check_edit, check_with_base_items}; +use crate::tests::{check, check_edit, check_with_base_items}; #[test] fn target_type_or_trait_in_impl_block() { @@ -308,3 +308,39 @@ fn bar() { "#]], ); } + +#[test] +fn expression_in_item_macro() { + check( + r#" +fn foo() -> u8 { 0 } + +macro_rules! foo { + ($expr:expr) => { + const BAR: u8 = $expr; + }; +} + +foo!(f$0); + "#, + expect![[r#" + ct BAR u8 + fn foo() fn() -> u8 + ma foo!(…) macro_rules! foo + bt u32 u32 + kw const + kw crate:: + kw false + kw for + kw if + kw if let + kw loop + kw match + kw self:: + kw true + kw unsafe + kw while + kw while let + "#]], + ); +} -- cgit 1.4.1-3-g733a5 From 753c62c8899abe05abcb7bc3cde8535f925e35bb Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 25 May 2025 20:15:58 +0300 Subject: Properly implement `might_be_inside_macro_call()` using semantic information instead of syntactical hacks And rename it to `is_inside_macro_call()` accordingly. --- .../rust-analyzer/crates/hir/src/semantics.rs | 72 +++++++++------------- .../crates/ide-completion/src/context.rs | 6 +- .../crates/ide-completion/src/context/analysis.rs | 33 +++++----- .../crates/ide-completion/src/tests/expression.rs | 50 +++++++++++++++ .../rust-analyzer/crates/ide-db/src/search.rs | 34 +++++----- src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs | 2 +- .../rust-analyzer/crates/ide-ssr/src/search.rs | 2 +- .../rust-analyzer/crates/ide/src/expand_macro.rs | 9 +-- .../crates/ide/src/highlight_related.rs | 2 +- 9 files changed, 125 insertions(+), 85 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index caa6700de9f..d855b6aab8a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -407,14 +407,14 @@ impl<'db> SemanticsImpl<'db> { res } - pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option { + pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option> { let sa = self.analyze_no_infer(macro_call.syntax())?; let macro_call = InFile::new(sa.file_id, macro_call); let file_id = sa.expand(self.db, macro_call)?; let node = self.parse_or_expand(file_id.into()); - Some(node) + Some(InFile::new(file_id.into(), node)) } pub fn check_cfg_attr(&self, attr: &ast::TokenTree) -> Option { @@ -468,10 +468,10 @@ impl<'db> SemanticsImpl<'db> { } /// If `item` has an attribute macro attached to it, expands it. - pub fn expand_attr_macro(&self, item: &ast::Item) -> Option> { + pub fn expand_attr_macro(&self, item: &ast::Item) -> Option>> { let src = self.wrap_node_infile(item.clone()); let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src.as_ref()))?; - Some(self.expand(macro_call_id)) + Some(self.expand(macro_call_id).map(|it| InFile::new(macro_call_id.into(), it))) } pub fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option { @@ -846,49 +846,35 @@ impl<'db> SemanticsImpl<'db> { res } - // FIXME: This isn't quite right wrt to inner attributes - /// Does a syntactic traversal to check whether this token might be inside a macro call - pub fn might_be_inside_macro_call(&self, token: &SyntaxToken) -> bool { - token.parent_ancestors().any(|ancestor| { + pub fn is_inside_macro_call(&self, token: InFile<&SyntaxToken>) -> bool { + // FIXME: Maybe `ancestors_with_macros()` is more suitable here? Currently + // this is only used on real (not macro) files so this is not a problem. + token.value.parent_ancestors().any(|ancestor| { if ast::MacroCall::can_cast(ancestor.kind()) { return true; } - // Check if it is an item (only items can have macro attributes) that has a non-builtin attribute. - let Some(item) = ast::Item::cast(ancestor) else { return false }; - item.attrs().any(|attr| { - let Some(meta) = attr.meta() else { return false }; - let Some(path) = meta.path() else { return false }; - if let Some(attr_name) = path.as_single_name_ref() { - let attr_name = attr_name.text(); - let attr_name = Symbol::intern(attr_name.as_str()); - if attr_name == sym::derive { - return true; - } - // We ignore `#[test]` and friends in the def map, so we cannot expand them. - // FIXME: We match by text. This is both hacky and incorrect (people can, and do, create - // other macros named `test`). We cannot fix that unfortunately because we use this method - // for speculative expansion in completion, which we cannot analyze. Fortunately, most macros - // named `test` are test-like, meaning their expansion is not terribly important for IDE. - if attr_name == sym::test - || attr_name == sym::bench - || attr_name == sym::test_case - || find_builtin_attr_idx(&attr_name).is_some() - { - return false; - } - } - let mut segments = path.segments(); - let mut next_segment_text = || segments.next().and_then(|it| it.name_ref()); - // `#[core::prelude::rust_2024::test]` or `#[std::prelude::rust_2024::test]`. - if next_segment_text().is_some_and(|it| matches!(&*it.text(), "core" | "std")) - && next_segment_text().is_some_and(|it| it.text() == "prelude") - && next_segment_text().is_some() - && next_segment_text() - .is_some_and(|it| matches!(&*it.text(), "test" | "bench" | "test_case")) - { - return false; + + let Some(item) = ast::Item::cast(ancestor) else { + return false; + }; + // Optimization to skip the semantic check. + if item.attrs().all(|attr| { + attr.simple_name() + .is_some_and(|attr| find_builtin_attr_idx(&Symbol::intern(&attr)).is_some()) + }) { + return false; + } + self.with_ctx(|ctx| { + if ctx.item_to_macro_call(token.with_value(&item)).is_some() { + return true; } - true + let adt = match item { + ast::Item::Struct(it) => it.into(), + ast::Item::Enum(it) => it.into(), + ast::Item::Union(it) => it.into(), + _ => return false, + }; + ctx.has_derives(token.with_value(&adt)) }) }) } 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 3baf1f3de61..5287627790a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -8,8 +8,8 @@ use std::{iter, ops::ControlFlow}; use base_db::RootQueryDb as _; use hir::{ - DisplayTarget, HasAttrs, Local, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, - Semantics, SemanticsScope, Symbol, Type, TypeInfo, + DisplayTarget, HasAttrs, InFile, Local, ModuleDef, ModuleSource, Name, PathResolution, + ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo, }; use ide_db::{ FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs, @@ -751,7 +751,7 @@ impl<'a> CompletionContext<'a> { original_offset, } = expand_and_analyze( &sema, - original_file.syntax().clone(), + InFile::new(editioned_file_id.into(), original_file.syntax().clone()), file_with_fake_ident.syntax().clone(), offset, &original_token, 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 284876ffc88..7a2230b3e36 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 @@ -1,7 +1,7 @@ //! Module responsible for analyzing the code surrounding the cursor for completion. use std::iter; -use hir::{ExpandResult, Semantics, Type, TypeInfo, Variant}; +use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant}; use ide_db::{RootDatabase, active_parameter::ActiveParameter}; use itertools::Either; use syntax::{ @@ -50,7 +50,7 @@ pub(super) struct AnalysisResult { pub(super) fn expand_and_analyze( sema: &Semantics<'_, RootDatabase>, - original_file: SyntaxNode, + original_file: InFile, speculative_file: SyntaxNode, offset: TextSize, original_token: &SyntaxToken, @@ -72,7 +72,7 @@ pub(super) fn expand_and_analyze( relative_offset, ) .unwrap_or(ExpansionResult { - original_file, + original_file: original_file.value, speculative_file, original_offset: offset, speculative_offset: fake_ident_token.text_range().start(), @@ -125,7 +125,7 @@ fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Opt /// the best we can do. fn expand_maybe_stop( sema: &Semantics<'_, RootDatabase>, - original_file: SyntaxNode, + original_file: InFile, speculative_file: SyntaxNode, original_offset: TextSize, fake_ident_token: SyntaxToken, @@ -142,17 +142,16 @@ fn expand_maybe_stop( return result; } - // This needs to come after the recursive call, because our "inside macro" detection is subtly wrong - // with regard to attribute macros named `test` that are not std's test. So hopefully we will expand - // them successfully above and be able to analyze. - // Left biased since there may already be an identifier token there, and we appended to it. - if !sema.might_be_inside_macro_call(&fake_ident_token) - && token_at_offset_ignore_whitespace(&original_file, original_offset + relative_offset) - .is_some_and(|original_token| !sema.might_be_inside_macro_call(&original_token)) + // We can't check whether the fake expansion is inside macro call, because that requires semantic info. + // But hopefully checking just the real one should be enough. + if token_at_offset_ignore_whitespace(&original_file.value, original_offset + relative_offset) + .is_some_and(|original_token| { + !sema.is_inside_macro_call(original_file.with_value(&original_token)) + }) { // Recursion base case. Some(ExpansionResult { - original_file, + original_file: original_file.value, speculative_file, original_offset, speculative_offset: fake_ident_token.text_range().start(), @@ -166,7 +165,7 @@ fn expand_maybe_stop( fn expand( sema: &Semantics<'_, RootDatabase>, - original_file: SyntaxNode, + original_file: InFile, speculative_file: SyntaxNode, original_offset: TextSize, fake_ident_token: SyntaxToken, @@ -176,7 +175,7 @@ fn expand( let parent_item = |item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast); - let original_node = token_at_offset_ignore_whitespace(&original_file, original_offset) + let original_node = token_at_offset_ignore_whitespace(&original_file.value, original_offset) .and_then(|token| token.parent_ancestors().find_map(ast::Item::cast)); let ancestor_items = iter::successors( Option::zip( @@ -249,7 +248,7 @@ fn expand( } // No attributes have been expanded, so look for macro_call! token trees or derive token trees - let orig_tt = ancestors_at_offset(&original_file, original_offset) + let orig_tt = ancestors_at_offset(&original_file.value, original_offset) .map_while(Either::::cast) .last()?; let spec_tt = ancestors_at_offset(&speculative_file, fake_ident_token.text_range().start()) @@ -292,7 +291,7 @@ fn expand( fake_mapped_tokens.into_iter().min_by_key(|(_, rank)| *rank) { return Some(ExpansionResult { - original_file, + original_file: original_file.value, speculative_file, original_offset, speculative_offset: fake_ident_token.text_range().start(), @@ -349,7 +348,7 @@ fn expand( } let result = expand_maybe_stop( sema, - actual_expansion.clone(), + InFile::new(file.into(), actual_expansion.clone()), fake_expansion.clone(), new_offset, fake_mapped_token, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index e5467767d42..b46e4c32061 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -2111,6 +2111,56 @@ fn foo() { ); } +#[test] +fn cfg_attr_attr_macro() { + check( + r#" +//- proc_macros: identity +#[cfg_attr(test, proc_macros::identity)] +fn foo() { + $0 +} + "#, + expect![[r#" + fn foo() fn() + md proc_macros + bt u32 u32 + kw async + kw const + kw crate:: + kw enum + kw extern + kw false + kw fn + kw for + kw if + kw if let + kw impl + kw impl for + kw let + kw letm + kw loop + kw match + kw mod + kw return + kw self:: + kw static + kw struct + kw trait + kw true + kw type + kw union + kw unsafe + kw use + kw while + kw while let + sn macro_rules + sn pd + sn ppd + "#]], + ); +} + #[test] fn escaped_label() { check( 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 30be5bc21b4..d4ab7592927 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -524,6 +524,7 @@ impl<'a> FindUsages<'a> { fn find_nodes<'b>( sema: &'b Semantics<'_, RootDatabase>, name: &str, + file_id: EditionedFileId, node: &syntax::SyntaxNode, offset: TextSize, ) -> impl Iterator + 'b { @@ -534,7 +535,7 @@ impl<'a> FindUsages<'a> { }) .into_iter() .flat_map(move |token| { - if sema.might_be_inside_macro_call(&token) { + if sema.is_inside_macro_call(InFile::new(file_id.into(), &token)) { sema.descend_into_macros_exact(token) } else { <_>::from([token]) @@ -654,11 +655,14 @@ impl<'a> FindUsages<'a> { let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone()); for offset in FindUsages::match_indices(&file_text, &finder, search_range) { - let usages = - FindUsages::find_nodes(sema, ¤t_to_process, &tree, offset) - .filter(|it| { - matches!(it.kind(), SyntaxKind::NAME | SyntaxKind::NAME_REF) - }); + let usages = FindUsages::find_nodes( + sema, + ¤t_to_process, + file_id, + &tree, + offset, + ) + .filter(|it| matches!(it.kind(), SyntaxKind::NAME | SyntaxKind::NAME_REF)); for usage in usages { if let Some(alias) = usage.parent().and_then(|it| { let path = ast::PathSegment::cast(it)?.parent_path(); @@ -813,7 +817,7 @@ impl<'a> FindUsages<'a> { let tree = LazyCell::new(move || this.sema.parse(file_id).syntax().clone()); for offset in FindUsages::match_indices(&file_text, finder, search_range) { - let usages = FindUsages::find_nodes(this.sema, name, &tree, offset) + let usages = FindUsages::find_nodes(this.sema, name, file_id, &tree, offset) .filter_map(ast::NameRef::cast); for usage in usages { let found_usage = usage @@ -970,8 +974,8 @@ impl<'a> FindUsages<'a> { return; } - for name in - Self::find_nodes(sema, name, &tree, offset).filter_map(ast::NameLike::cast) + for name in Self::find_nodes(sema, name, file_id, &tree, offset) + .filter_map(ast::NameLike::cast) { if match name { ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink), @@ -985,8 +989,8 @@ impl<'a> FindUsages<'a> { // Search for occurrences of the `Self` referring to our type if let Some((self_ty, finder)) = &include_self_kw_refs { for offset in Self::match_indices(&text, finder, search_range) { - for name_ref in - Self::find_nodes(sema, "Self", &tree, offset).filter_map(ast::NameRef::cast) + for name_ref in Self::find_nodes(sema, "Self", file_id, &tree, offset) + .filter_map(ast::NameRef::cast) { if self.found_self_ty_name_ref(self_ty, &name_ref, sink) { return; @@ -1010,7 +1014,7 @@ impl<'a> FindUsages<'a> { let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone()); for offset in Self::match_indices(&text, finder, search_range) { - for name_ref in Self::find_nodes(sema, "super", &tree, offset) + for name_ref in Self::find_nodes(sema, "super", file_id, &tree, offset) .filter_map(ast::NameRef::cast) { if self.found_name_ref(&name_ref, sink) { @@ -1020,7 +1024,7 @@ impl<'a> FindUsages<'a> { } if let Some(finder) = &is_crate_root { for offset in Self::match_indices(&text, finder, search_range) { - for name_ref in Self::find_nodes(sema, "crate", &tree, offset) + for name_ref in Self::find_nodes(sema, "crate", file_id, &tree, offset) .filter_map(ast::NameRef::cast) { if self.found_name_ref(&name_ref, sink) { @@ -1064,8 +1068,8 @@ impl<'a> FindUsages<'a> { let finder = &Finder::new("self"); for offset in Self::match_indices(&text, finder, search_range) { - for name_ref in - Self::find_nodes(sema, "self", &tree, offset).filter_map(ast::NameRef::cast) + for name_ref in Self::find_nodes(sema, "self", file_id, &tree, offset) + .filter_map(ast::NameRef::cast) { if self.found_self_module_name_ref(&name_ref, sink) { return; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs index 339c199ec29..43c56ac8bec 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs @@ -287,7 +287,7 @@ impl<'db> MatchFinder<'db> { if let Some(expanded) = self.sema.expand_macro_call(¯o_call) { if let Some(tt) = macro_call.token_tree() { self.output_debug_for_nodes_at_range( - &expanded, + &expanded.value, range, &Some(self.sema.original_range(tt.syntax())), out, diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs index d89911fca40..9afbedbb1ab 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs @@ -194,7 +194,7 @@ impl MatchFinder<'_> { // nodes that originated entirely from within the token tree of the macro call. // i.e. we don't want to match something that came from the macro itself. if let Some(range) = self.sema.original_range_opt(tt.syntax()) { - self.slow_scan_node(&expanded, rule, &Some(range), matches_out); + self.slow_scan_node(&expanded.value, rule, &Some(range), matches_out); } } } diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 241a702038d..9beed2cac13 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -146,10 +146,11 @@ fn expand_macro_recur( offset_in_original_node: TextSize, ) -> Option { let ExpandResult { value: expanded, err } = match macro_call { - item @ ast::Item::MacroCall(macro_call) => { - sema.expand_attr_macro(item).or_else(|| sema.expand_allowed_builtins(macro_call))? - } - item => sema.expand_attr_macro(item)?, + item @ ast::Item::MacroCall(macro_call) => sema + .expand_attr_macro(item) + .map(|it| it.map(|it| it.value)) + .or_else(|| sema.expand_allowed_builtins(macro_call))?, + item => sema.expand_attr_macro(item)?.map(|it| it.value), }; let expanded = expanded.clone_for_update(); if let Some(err) = err { 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 fb8dbcfc735..520ba39a238 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -653,7 +653,7 @@ impl<'a> WalkExpandedExprCtx<'a> { expr.macro_call().and_then(|call| self.sema.expand_macro_call(&call)) { match_ast! { - match expanded { + match (expanded.value) { ast::MacroStmts(it) => { self.handle_expanded(it, cb); }, -- cgit 1.4.1-3-g733a5 From 1e9e17704adfc6bd6b01a0031b73fbc1682a0f1f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 21 May 2025 15:34:15 +0000 Subject: Move some code around in codegen_call_terminator --- compiler/rustc_codegen_ssa/src/mir/block.rs | 202 ++++++++++++++-------------- 1 file changed, 103 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 922b8a5824b..de827a475c4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -8,7 +8,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::mir::{self, AssertKind, 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}; +use rustc_middle::ty::{self, Instance, List, Ty}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::source_map::Spanned; @@ -827,7 +827,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper: &TerminatorCodegenHelper<'tcx>, bx: &mut Bx, intrinsic: ty::IntrinsicDef, - instance: Option>, + instance: Instance<'tcx>, source_info: mir::SourceInfo, target: Option, unwind: mir::UnwindAction, @@ -837,7 +837,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) { - let ty = instance.unwrap().args.type_at(0); + let ty = instance.args.type_at(0); let do_panic = !bx .tcx() @@ -910,35 +910,116 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let callee = self.codegen_operand(bx, func); let (instance, mut llfn) = match *callee.layout.ty.kind() { - ty::FnDef(def_id, args) => ( - Some(ty::Instance::expect_resolve( + ty::FnDef(def_id, generic_args) => { + let instance = ty::Instance::expect_resolve( bx.tcx(), bx.typing_env(), def_id, - args, + generic_args, fn_span, - )), - None, - ), + ); + + let instance = match instance.def { + // We don't need AsyncDropGlueCtorShim here because it is not `noop func`, + // it is `func returning noop future` + ty::InstanceKind::DropGlue(_, None) => { + // Empty drop glue; a no-op. + let target = target.unwrap(); + return helper.funclet_br(self, bx, target, mergeable_succ); + } + ty::InstanceKind::Intrinsic(def_id) => { + let intrinsic = bx.tcx().intrinsic(def_id).unwrap(); + if let Some(merging_succ) = self.codegen_panic_intrinsic( + &helper, + bx, + intrinsic, + instance, + source_info, + target, + unwind, + mergeable_succ, + ) { + return merging_succ; + } + + let fn_abi = bx.fn_abi_of_instance(instance, List::empty()); + + let mut llargs = Vec::with_capacity(1); + let ret_dest = self.make_return_dest( + bx, + destination, + &fn_abi.ret, + &mut llargs, + Some(intrinsic), + ); + let dest = match ret_dest { + _ if fn_abi.ret.is_indirect() => llargs[0], + ReturnDest::Nothing => bx.const_undef(bx.type_ptr()), + ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => { + dst.val.llval + } + ReturnDest::DirectOperand(_) => { + bug!("Cannot use direct operand with an intrinsic call") + } + }; + + let args: Vec<_> = + args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); + + if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) + { + let location = self.get_caller_location( + bx, + mir::SourceInfo { span: fn_span, ..source_info }, + ); + + assert_eq!(llargs, []); + if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { + location.val.store(bx, tmp); + } + self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate()); + return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ); + } + + match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) + { + Ok(()) => { + if let ReturnDest::IndirectOperand(dst, _) = ret_dest { + self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval); + } + + return if let Some(target) = target { + helper.funclet_br(self, bx, target, mergeable_succ) + } else { + bx.unreachable(); + MergingSucc::False + }; + } + Err(instance) => { + if intrinsic.must_be_overridden { + span_bug!( + span, + "intrinsic {} must be overridden by codegen backend, but isn't", + intrinsic.name, + ); + } + instance + } + } + } + _ => instance, + }; + + (Some(instance), None) + } ty::FnPtr(..) => (None, Some(callee.immediate())), _ => bug!("{} is not callable", callee.layout.ty), }; - let def = instance.map(|i| i.def); - - // We don't need AsyncDropGlueCtorShim here because it is not `noop func`, - // it is `func returning noop future` - if let Some(ty::InstanceKind::DropGlue(_, None)) = def { - // Empty drop glue; a no-op. - let target = target.unwrap(); - return helper.funclet_br(self, bx, target, mergeable_succ); - } - // FIXME(eddyb) avoid computing this if possible, when `instance` is // available - right now `sig` is only needed for getting the `abi` // and figuring out how many extra args were passed to a C-variadic `fn`. let sig = callee.layout.ty.fn_sig(bx.tcx()); - let abi = sig.abi(); let extra_args = &args[sig.inputs().skip_binder().len()..]; let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| { @@ -954,83 +1035,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The arguments we'll be passing. Plus one to account for outptr, if used. let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; - let instance = match def { - Some(ty::InstanceKind::Intrinsic(def_id)) => { - let intrinsic = bx.tcx().intrinsic(def_id).unwrap(); - if let Some(merging_succ) = self.codegen_panic_intrinsic( - &helper, - bx, - intrinsic, - instance, - source_info, - target, - unwind, - mergeable_succ, - ) { - return merging_succ; - } - - let mut llargs = Vec::with_capacity(1); - let ret_dest = self.make_return_dest( - bx, - destination, - &fn_abi.ret, - &mut llargs, - Some(intrinsic), - ); - let dest = match ret_dest { - _ if fn_abi.ret.is_indirect() => llargs[0], - ReturnDest::Nothing => bx.const_undef(bx.type_ptr()), - ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.val.llval, - ReturnDest::DirectOperand(_) => { - bug!("Cannot use direct operand with an intrinsic call") - } - }; - - let args: Vec<_> = - args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); - - if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) { - let location = self - .get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info }); - - assert_eq!(llargs, []); - if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { - location.val.store(bx, tmp); - } - self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate()); - return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ); - } - - let instance = *instance.as_ref().unwrap(); - match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) { - Ok(()) => { - if let ReturnDest::IndirectOperand(dst, _) = ret_dest { - self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval); - } - - return if let Some(target) = target { - helper.funclet_br(self, bx, target, mergeable_succ) - } else { - bx.unreachable(); - MergingSucc::False - }; - } - Err(instance) => { - if intrinsic.must_be_overridden { - span_bug!( - span, - "intrinsic {} must be overridden by codegen backend, but isn't", - intrinsic.name, - ); - } - Some(instance) - } - } - } - _ => instance, - }; - let mut llargs = Vec::with_capacity(arg_count); // We still need to call `make_return_dest` even if there's no `target`, since @@ -1040,7 +1044,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let destination = target.map(|target| (return_dest, target)); // Split the rust-call tupled arguments off. - let (first_args, untuple) = if abi == ExternAbi::RustCall + let (first_args, untuple) = if sig.abi() == ExternAbi::RustCall && let Some((tup, args)) = args.split_last() { (args, Some(tup)) @@ -1055,7 +1059,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 'make_args: for (i, arg) in first_args.iter().enumerate() { let mut op = self.codegen_operand(bx, &arg.node); - if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, def) { + if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, instance.map(|i| i.def)) { match op.val { Pair(data_ptr, meta) => { // In the case of Rc, we need to explicitly pass a -- cgit 1.4.1-3-g733a5 From e4700e76d83428a99f2c7a8b19d3bf50606cf7e1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 22 May 2025 11:17:51 +0000 Subject: Always use fn_span in codegen_call_terminator --- compiler/rustc_codegen_ssa/src/mir/block.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index de827a475c4..beb13ba28bc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -903,8 +903,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_span: Span, mergeable_succ: bool, ) -> MergingSucc { - let source_info = terminator.source_info; - let span = source_info.span; + let source_info = mir::SourceInfo { span: fn_span, ..terminator.source_info }; // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. let callee = self.codegen_operand(bx, func); @@ -968,10 +967,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) { - let location = self.get_caller_location( - bx, - mir::SourceInfo { span: fn_span, ..source_info }, - ); + let location = self.get_caller_location(bx, source_info); assert_eq!(llargs, []); if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { @@ -981,8 +977,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ); } - match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) - { + match Self::codegen_intrinsic_call( + bx, instance, fn_abi, &args, dest, fn_span, + ) { Ok(()) => { if let ReturnDest::IndirectOperand(dst, _) = ret_dest { self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval); @@ -998,7 +995,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Err(instance) => { if intrinsic.must_be_overridden { span_bug!( - span, + fn_span, "intrinsic {} must be overridden by codegen backend, but isn't", intrinsic.name, ); @@ -1113,7 +1110,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Make sure that we've actually unwrapped the rcvr down // to a pointer or ref to `dyn* Trait`. if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() { - span_bug!(span, "can't codegen a virtual call on {:#?}", op); + span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op); } let place = op.deref(bx.cx()); let data_place = place.project_field(bx, 0); @@ -1129,7 +1126,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { continue; } _ => { - span_bug!(span, "can't codegen a virtual call on {:#?}", op); + span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op); } } } @@ -1179,8 +1176,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir_args + 1, "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR: {instance:?} {fn_span:?} {fn_abi:?}", ); - let location = - self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info }); + let location = self.get_caller_location(bx, source_info); debug!( "codegen_call_terminator({:?}): location={:?} (fn_span {:?})", terminator, location, fn_span @@ -1199,9 +1195,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ptr = match (instance, llfn) { (Some(instance), None) => bx.get_fn_addr(instance), (_, Some(llfn)) => llfn, - _ => span_bug!(span, "no instance or llfn for call"), + _ => span_bug!(fn_span, "no instance or llfn for call"), }; - self.set_debug_loc(bx, mir::SourceInfo { span: fn_span, ..source_info }); + self.set_debug_loc(bx, source_info); helper.do_call( self, bx, -- cgit 1.4.1-3-g733a5 From c83358beb5f40a8b1c6e422f229ca4db1f927599 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 22 May 2025 13:50:47 +0000 Subject: Move caller_location handling into codegen_intrinsic_call --- compiler/rustc_codegen_ssa/src/mir/block.rs | 25 +++++++++---------------- compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 13 +++++++++++-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index beb13ba28bc..1d11b907e90 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -11,8 +11,8 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, List, Ty}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::{Span, sym}; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use tracing::{debug, info}; @@ -965,20 +965,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let args: Vec<_> = args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); - if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) - { - let location = self.get_caller_location(bx, source_info); - - assert_eq!(llargs, []); - if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { - location.val.store(bx, tmp); - } - self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate()); - return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ); - } - - match Self::codegen_intrinsic_call( - bx, instance, fn_abi, &args, dest, fn_span, + match self.codegen_intrinsic_call( + bx, + instance, + fn_abi, + &args, + dest, + source_info, ) { Ok(()) => { if let ReturnDest::IndirectOperand(dst, _) = ret_dest { @@ -1667,7 +1660,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { tuple.layout.fields.count() } - fn get_caller_location( + pub(super) fn get_caller_location( &mut self, bx: &mut Bx, source_info: mir::SourceInfo, diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index b0fcfee2adf..6cdd8480cbe 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,8 +1,9 @@ use rustc_abi::WrappingRange; +use rustc_middle::mir::SourceInfo; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; -use rustc_span::{Span, sym}; +use rustc_span::sym; use rustc_target::callconv::{FnAbi, PassMode}; use super::FunctionCx; @@ -52,13 +53,15 @@ fn memset_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// In the `Err` case, returns the instance that should be called instead. pub fn codegen_intrinsic_call( + &mut self, bx: &mut Bx, instance: ty::Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Bx::Value>], llresult: Bx::Value, - span: Span, + source_info: SourceInfo, ) -> Result<(), ty::Instance<'tcx>> { + let span = source_info.span; let callee_ty = instance.ty(bx.tcx(), bx.typing_env()); let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else { @@ -105,6 +108,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return Ok(()); } + sym::caller_location => { + let location = self.get_caller_location(bx, source_info); + location.val.store(bx, result); + return Ok(()); + } + sym::va_start => bx.va_start(args[0].immediate()), sym::va_end => bx.va_end(args[0].immediate()), sym::size_of_val => { -- cgit 1.4.1-3-g733a5 From 6016f84e716c443f64c491a26f5ec1dfd42f2491 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 22 May 2025 14:15:41 +0000 Subject: Pass PlaceRef rather than Bx::Value to codegen_intrinsic_call --- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 21 ++++----- compiler/rustc_codegen_llvm/src/intrinsic.rs | 50 ++++++++++------------ compiler/rustc_codegen_ssa/src/mir/block.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 5 +-- compiler/rustc_codegen_ssa/src/traits/intrinsic.rs | 3 +- 5 files changed, 38 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index ba65c8205a5..18dabe9ea16 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -22,7 +22,7 @@ use rustc_codegen_ssa::traits::{ }; use rustc_middle::bug; #[cfg(feature = "master")] -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; @@ -202,7 +202,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], - llresult: RValue<'gcc>, + result: PlaceRef<'tcx, RValue<'gcc>>, span: Span, ) -> Result<(), Instance<'tcx>> { let tcx = self.tcx; @@ -221,7 +221,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let name_str = name.as_str(); let llret_ty = self.layout_of(ret_ty).gcc_type(self); - let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); let simple = get_simple_intrinsic(self, name); let simple_func = get_simple_function(self, name); @@ -271,7 +270,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc args[0].immediate(), args[1].immediate(), args[2].immediate(), - llresult, + result, ); return Ok(()); } @@ -1230,14 +1229,13 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, - dest: RValue<'gcc>, + dest: PlaceRef<'tcx, RValue<'gcc>>, ) { if bx.sess().panic_strategy() == PanicStrategy::Abort { bx.call(bx.type_void(), None, None, try_func, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. - let ret_align = bx.tcx.data_layout.i32_align.abi; - bx.store(bx.const_i32(0), dest, ret_align); + OperandValue::Immediate(bx.const_i32(0)).store(bx, dest); } else { if wants_msvc_seh(bx.sess()) { unimplemented!(); @@ -1261,12 +1259,12 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( // functions in play. By calling a shim we're guaranteed that our shim will have // the right personality function. #[cfg(feature = "master")] -fn codegen_gnu_try<'gcc>( - bx: &mut Builder<'_, 'gcc, '_>, +fn codegen_gnu_try<'gcc, 'tcx>( + bx: &mut Builder<'_, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, catch_func: RValue<'gcc>, - dest: RValue<'gcc>, + dest: PlaceRef<'tcx, RValue<'gcc>>, ) { let cx: &CodegenCx<'gcc, '_> = bx.cx; let (llty, func) = get_rust_try_fn(cx, &mut |mut bx| { @@ -1322,8 +1320,7 @@ fn codegen_gnu_try<'gcc>( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None); - let i32_align = bx.tcx().data_layout.i32_align.abi; - bx.store(ret, dest, i32_align); + OperandValue::Immediate(ret).store(bx, dest); } // Helper function used to get a handle to the `__rust_try` function used to diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 5ca57375292..067dd9b1681 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -167,7 +167,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { instance: ty::Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, &'ll Value>], - llresult: &'ll Value, + result: PlaceRef<'tcx, &'ll Value>, span: Span, ) -> Result<(), ty::Instance<'tcx>> { let tcx = self.tcx; @@ -184,7 +184,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let name = tcx.item_name(def_id); let llret_ty = self.layout_of(ret_ty).llvm_type(self); - let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); let simple = get_simple_intrinsic(self, name); let llval = match name { @@ -255,7 +254,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { args[0].immediate(), args[1].immediate(), args[2].immediate(), - llresult, + result, ); return Ok(()); } @@ -688,20 +687,19 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } } -fn catch_unwind_intrinsic<'ll>( - bx: &mut Builder<'_, 'll, '_>, +fn catch_unwind_intrinsic<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, - dest: &'ll Value, + dest: PlaceRef<'tcx, &'ll Value>, ) { if bx.sess().panic_strategy() == PanicStrategy::Abort { let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); bx.call(try_func_ty, None, None, try_func, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. - let ret_align = bx.tcx().data_layout.i32_align.abi; - bx.store(bx.const_i32(0), dest, ret_align); + OperandValue::Immediate(bx.const_i32(0)).store(bx, dest); } else if wants_msvc_seh(bx.sess()) { codegen_msvc_try(bx, try_func, data, catch_func, dest); } else if wants_wasm_eh(bx.sess()) { @@ -720,12 +718,12 @@ fn catch_unwind_intrinsic<'ll>( // instructions are meant to work for all targets, as of the time of this // writing, however, LLVM does not recommend the usage of these new instructions // as the old ones are still more optimized. -fn codegen_msvc_try<'ll>( - bx: &mut Builder<'_, 'll, '_>, +fn codegen_msvc_try<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, - dest: &'ll Value, + dest: PlaceRef<'tcx, &'ll Value>, ) { let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| { bx.set_personality_fn(bx.eh_personality()); @@ -865,17 +863,16 @@ fn codegen_msvc_try<'ll>( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); - let i32_align = bx.tcx().data_layout.i32_align.abi; - bx.store(ret, dest, i32_align); + OperandValue::Immediate(ret).store(bx, dest); } // WASM's definition of the `rust_try` function. -fn codegen_wasm_try<'ll>( - bx: &mut Builder<'_, 'll, '_>, +fn codegen_wasm_try<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, - dest: &'ll Value, + dest: PlaceRef<'tcx, &'ll Value>, ) { let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| { bx.set_personality_fn(bx.eh_personality()); @@ -939,8 +936,7 @@ fn codegen_wasm_try<'ll>( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); - let i32_align = bx.tcx().data_layout.i32_align.abi; - bx.store(ret, dest, i32_align); + OperandValue::Immediate(ret).store(bx, dest); } // Definition of the standard `try` function for Rust using the GNU-like model @@ -954,12 +950,12 @@ fn codegen_wasm_try<'ll>( // function calling it, and that function may already have other personality // functions in play. By calling a shim we're guaranteed that our shim will have // the right personality function. -fn codegen_gnu_try<'ll>( - bx: &mut Builder<'_, 'll, '_>, +fn codegen_gnu_try<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, - dest: &'ll Value, + dest: PlaceRef<'tcx, &'ll Value>, ) { let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| { // Codegens the shims described above: @@ -1006,19 +1002,18 @@ fn codegen_gnu_try<'ll>( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); - let i32_align = bx.tcx().data_layout.i32_align.abi; - bx.store(ret, dest, i32_align); + OperandValue::Immediate(ret).store(bx, dest); } // Variant of codegen_gnu_try used for emscripten where Rust panics are // implemented using C++ exceptions. Here we use exceptions of a specific type // (`struct rust_panic`) to represent Rust panics. -fn codegen_emcc_try<'ll>( - bx: &mut Builder<'_, 'll, '_>, +fn codegen_emcc_try<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, - dest: &'ll Value, + dest: PlaceRef<'tcx, &'ll Value>, ) { let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| { // Codegens the shims described above: @@ -1089,8 +1084,7 @@ fn codegen_emcc_try<'ll>( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); - let i32_align = bx.tcx().data_layout.i32_align.abi; - bx.store(ret, dest, i32_align); + OperandValue::Immediate(ret).store(bx, dest); } // Helper function to give a Block to a closure to codegen a shim function. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 1d11b907e90..1a291b17886 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -965,12 +965,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let args: Vec<_> = args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); + let result = PlaceRef::new_sized(dest, fn_abi.ret.layout); + match self.codegen_intrinsic_call( bx, instance, fn_abi, &args, - dest, + result, source_info, ) { Ok(()) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 6cdd8480cbe..6a077883298 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { instance: ty::Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Bx::Value>], - llresult: Bx::Value, + result: PlaceRef<'tcx, Bx::Value>, source_info: SourceInfo, ) -> Result<(), ty::Instance<'tcx>> { let span = source_info.span; @@ -100,7 +100,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let llret_ty = bx.backend_type(bx.layout_of(ret_ty)); - let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); let llval = match name { sym::abort => { @@ -537,7 +536,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => { // Need to use backend-specific things in the implementation. - return bx.codegen_intrinsic_call(instance, fn_abi, args, llresult, span); + return bx.codegen_intrinsic_call(instance, fn_abi, args, result, span); } }; diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index 88cf8dbf0c5..f9d6dab6faf 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -4,6 +4,7 @@ use rustc_target::callconv::FnAbi; use super::BackendTypes; use crate::mir::operand::OperandRef; +use crate::mir::place::PlaceRef; pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes { /// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`, @@ -16,7 +17,7 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes { instance: ty::Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Self::Value>], - llresult: Self::Value, + result: PlaceRef<'tcx, Self::Value>, span: Span, ) -> Result<(), ty::Instance<'tcx>>; -- cgit 1.4.1-3-g733a5 From 0a14e1b2e7483179fa74f44d3c198c33325f6d29 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 22 May 2025 14:58:58 +0000 Subject: Remove usage of FnAbi in codegen_intrinsic_call --- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 32 ++++++++-------------- compiler/rustc_codegen_llvm/src/intrinsic.rs | 30 +++++++------------- compiler/rustc_codegen_ssa/src/mir/block.rs | 10 ++----- compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 18 +++++------- compiler/rustc_codegen_ssa/src/traits/intrinsic.rs | 4 +-- 5 files changed, 31 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 18dabe9ea16..1bcb891a250 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -26,7 +26,7 @@ use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, PassMode}; use rustc_target::spec::PanicStrategy; #[cfg(feature = "master")] @@ -200,7 +200,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc fn codegen_intrinsic_call( &mut self, instance: Instance<'tcx>, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], result: PlaceRef<'tcx, RValue<'gcc>>, span: Span, @@ -285,17 +284,10 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::volatile_load | sym::unaligned_volatile_load => { - let tp_ty = fn_args.type_at(0); let ptr = args[0].immediate(); - let layout = self.layout_of(tp_ty); - let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode { - let gcc_ty = ty.gcc_type(self); - self.volatile_load(gcc_ty, ptr) - } else { - self.volatile_load(layout.gcc_type(self), ptr) - }; + let load = self.volatile_load(result.layout.gcc_type(self), ptr); // TODO(antoyo): set alignment. - if let BackendRepr::Scalar(scalar) = layout.backend_repr { + if let BackendRepr::Scalar(scalar) = result.layout.backend_repr { self.to_immediate_scalar(load, scalar) } else { load @@ -510,16 +502,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc _ => return Err(Instance::new_raw(instance.def_id(), instance.args)), }; - if !fn_abi.ret.is_ignore() { - if let PassMode::Cast { cast: ref ty, .. } = fn_abi.ret.mode { - let ptr_llty = self.type_ptr_to(ty.gcc_type(self)); - let ptr = self.pointercast(result.val.llval, ptr_llty); - self.store(value, ptr, result.val.align); - } else { - OperandRef::from_immediate_or_packed_pair(self, value, result.layout) - .val - .store(self, result); - } + if result.layout.ty.is_bool() { + OperandRef::from_immediate_or_packed_pair(self, value, result.layout) + .val + .store(self, result); + } else if !result.layout.ty.is_unit() { + let ptr_llty = self.type_ptr_to(result.layout.gcc_type(self)); + let ptr = self.pointercast(result.val.llval, ptr_llty); + self.store(value, ptr, result.val.align); } Ok(()) } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 067dd9b1681..e8629aeebb9 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -15,11 +15,10 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; use rustc_symbol_mangling::mangle_internal_symbol; -use rustc_target::callconv::{FnAbi, PassMode}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use tracing::debug; -use crate::abi::{FnAbiLlvmExt, LlvmType}; +use crate::abi::FnAbiLlvmExt; use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, Metadata}; @@ -165,7 +164,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn codegen_intrinsic_call( &mut self, instance: ty::Instance<'tcx>, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, &'ll Value>], result: PlaceRef<'tcx, &'ll Value>, span: Span, @@ -263,7 +261,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { self.call_intrinsic("llvm.va_copy", &[args[0].immediate(), args[1].immediate()]) } sym::va_arg => { - match fn_abi.ret.layout.backend_repr { + match result.layout.backend_repr { BackendRepr::Scalar(scalar) => { match scalar.primitive() { Primitive::Int(..) => { @@ -298,18 +296,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::volatile_load | sym::unaligned_volatile_load => { - let tp_ty = fn_args.type_at(0); let ptr = args[0].immediate(); - let load = if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode { - let llty = ty.llvm_type(self); - self.volatile_load(llty, ptr) - } else { - self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr) - }; + let load = self.volatile_load(result.layout.llvm_type(self), ptr); let align = if name == sym::unaligned_volatile_load { 1 } else { - self.align_of(tp_ty).bytes() as u32 + result.layout.align.abi.bytes() as u32 }; unsafe { llvm::LLVMSetAlignment(load, align); @@ -628,14 +620,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } }; - if !fn_abi.ret.is_ignore() { - if let PassMode::Cast { .. } = &fn_abi.ret.mode { - self.store(llval, result.val.llval, result.val.align); - } else { - OperandRef::from_immediate_or_packed_pair(self, llval, result.layout) - .val - .store(self, result); - } + if result.layout.ty.is_bool() { + OperandRef::from_immediate_or_packed_pair(self, llval, result.layout) + .val + .store(self, result); + } else if !result.layout.ty.is_unit() { + self.store_to_place(llval, result.val); } Ok(()) } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 1a291b17886..a2565c4f69d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -967,14 +967,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let result = PlaceRef::new_sized(dest, fn_abi.ret.layout); - match self.codegen_intrinsic_call( - bx, - instance, - fn_abi, - &args, - result, - source_info, - ) { + match self.codegen_intrinsic_call(bx, instance, &args, result, source_info) + { Ok(()) => { if let ReturnDest::IndirectOperand(dst, _) = ret_dest { self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 6a077883298..a6d159c51e1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -4,7 +4,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::sym; -use rustc_target::callconv::{FnAbi, PassMode}; use super::FunctionCx; use super::operand::OperandRef; @@ -56,7 +55,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, bx: &mut Bx, instance: ty::Instance<'tcx>, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Bx::Value>], result: PlaceRef<'tcx, Bx::Value>, source_info: SourceInfo, @@ -536,18 +534,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => { // Need to use backend-specific things in the implementation. - return bx.codegen_intrinsic_call(instance, fn_abi, args, result, span); + return bx.codegen_intrinsic_call(instance, args, result, span); } }; - if !fn_abi.ret.is_ignore() { - if let PassMode::Cast { .. } = &fn_abi.ret.mode { - bx.store_to_place(llval, result.val); - } else { - OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout) - .val - .store(bx, result); - } + if result.layout.ty.is_bool() { + OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout) + .val + .store(bx, result); + } else if !result.layout.ty.is_unit() { + bx.store_to_place(llval, result.val); } Ok(()) } diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index f9d6dab6faf..a07c569a032 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -1,6 +1,5 @@ -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty; use rustc_span::Span; -use rustc_target::callconv::FnAbi; use super::BackendTypes; use crate::mir::operand::OperandRef; @@ -15,7 +14,6 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes { fn codegen_intrinsic_call( &mut self, instance: ty::Instance<'tcx>, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Self::Value>], result: PlaceRef<'tcx, Self::Value>, span: Span, -- cgit 1.4.1-3-g733a5 From 7122648e3403bbbd471cd2667d5960a109bb9bd7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 22 May 2025 17:49:28 +0000 Subject: Don't depend on FnAbi for intrinsics Intrinsics are not real functions and as such don't have any calling convention. Trying to compute a calling convention for an intrinsic anyway is a nonsensical operation. --- compiler/rustc_codegen_ssa/src/mir/block.rs | 74 ++++++++++++++++------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a2565c4f69d..cb8088e9efb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -8,7 +8,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::mir::{self, AssertKind, 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, List, Ty}; +use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::Span; @@ -941,37 +941,55 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return merging_succ; } - let fn_abi = bx.fn_abi_of_instance(instance, List::empty()); + let result_layout = + self.cx.layout_of(self.monomorphized_place_ty(destination.as_ref())); - let mut llargs = Vec::with_capacity(1); - let ret_dest = self.make_return_dest( - bx, - destination, - &fn_abi.ret, - &mut llargs, - Some(intrinsic), - ); - let dest = match ret_dest { - _ if fn_abi.ret.is_indirect() => llargs[0], - ReturnDest::Nothing => bx.const_undef(bx.type_ptr()), - ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => { - dst.val.llval - } - ReturnDest::DirectOperand(_) => { - bug!("Cannot use direct operand with an intrinsic call") + let (result, store_in_local) = if result_layout.is_zst() { + ( + PlaceRef::new_sized(bx.const_undef(bx.type_ptr()), result_layout), + None, + ) + } else if let Some(local) = destination.as_local() { + match self.locals[local] { + LocalRef::Place(dest) => (dest, None), + LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), + LocalRef::PendingOperand => { + // Currently, intrinsics always need a location to store + // the result, so we create a temporary `alloca` for the + // result. + let tmp = PlaceRef::alloca(bx, result_layout); + tmp.storage_live(bx); + (tmp, Some(local)) + } + LocalRef::Operand(_) => { + bug!("place local already assigned to"); + } } + } else { + (self.codegen_place(bx, destination.as_ref()), None) }; + if result.val.align < result.layout.align.abi { + // Currently, MIR code generation does not create calls + // that store directly to fields of packed structs (in + // fact, the calls it creates write only to temps). + // + // If someone changes that, please update this code path + // to create a temporary. + span_bug!(self.mir.span, "can't directly store to unaligned value"); + } + let args: Vec<_> = args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); - let result = PlaceRef::new_sized(dest, fn_abi.ret.layout); - match self.codegen_intrinsic_call(bx, instance, &args, result, source_info) { Ok(()) => { - if let ReturnDest::IndirectOperand(dst, _) = ret_dest { - self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval); + if let Some(local) = store_in_local { + let op = bx.load_operand(result); + result.storage_dead(bx); + self.overwrite_local(local, LocalRef::Operand(op)); + self.debug_introduce_local(bx, local); } return if let Some(target) = target { @@ -1026,7 +1044,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // We still need to call `make_return_dest` even if there's no `target`, since // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited, // and `make_return_dest` adds the return-place indirect pointer to `llargs`. - let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None); + let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs); let destination = target.map(|target| (return_dest, target)); // Split the rust-call tupled arguments off. @@ -1857,7 +1875,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { dest: mir::Place<'tcx>, fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec, - intrinsic: Option, ) -> ReturnDest<'tcx, Bx::Value> { // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { @@ -1877,13 +1894,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { tmp.storage_live(bx); llargs.push(tmp.val.llval); ReturnDest::IndirectOperand(tmp, index) - } else if intrinsic.is_some() { - // Currently, intrinsics always need a location to store - // the result, so we create a temporary `alloca` for the - // result. - let tmp = PlaceRef::alloca(bx, fn_ret.layout); - tmp.storage_live(bx); - ReturnDest::IndirectOperand(tmp, index) } else { ReturnDest::DirectOperand(index) }; @@ -1893,7 +1903,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } else { - self.codegen_place(bx, mir::PlaceRef { local: dest.local, projection: dest.projection }) + self.codegen_place(bx, dest.as_ref()) }; if fn_ret.is_indirect() { if dest.val.align < dest.layout.align.abi { -- cgit 1.4.1-3-g733a5 From 165fb988499b771afb7c2ddb60f05e9e337afb6a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 23 May 2025 08:30:58 +0000 Subject: Reduce indentation in codegen_panic_intrinsic --- compiler/rustc_codegen_ssa/src/mir/block.rs | 96 ++++++++++++++--------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index cb8088e9efb..1baab62ae43 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -836,58 +836,56 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Emit a panic or a no-op for `assert_*` intrinsics. // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. - if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) { - let ty = instance.args.type_at(0); - - let do_panic = !bx - .tcx() - .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty))) - .expect("expect to have layout during codegen"); - - let layout = bx.layout_of(ty); - - Some(if do_panic { - let msg_str = with_no_visible_paths!({ - with_no_trimmed_paths!({ - if layout.is_uninhabited() { - // Use this error even for the other intrinsics as it is more precise. - format!("attempted to instantiate uninhabited type `{ty}`") - } else if requirement == ValidityRequirement::Zero { - format!("attempted to zero-initialize type `{ty}`, which is invalid") - } else { - format!( - "attempted to leave type `{ty}` uninitialized, which is invalid" - ) - } - }) - }); - let msg = bx.const_str(&msg_str); + let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) else { + return None; + }; - // Obtain the panic entry point. - let (fn_abi, llfn, instance) = - common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind); + let ty = instance.args.type_at(0); - // Codegen the actual panic invoke/call. - helper.do_call( - self, - bx, - fn_abi, - llfn, - &[msg.0, msg.1], - target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)), - unwind, - &[], - Some(instance), - mergeable_succ, - ) - } else { - // a NOP - let target = target.unwrap(); - helper.funclet_br(self, bx, target, mergeable_succ) - }) - } else { - None + let is_valid = bx + .tcx() + .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty))) + .expect("expect to have layout during codegen"); + + if is_valid { + // a NOP + let target = target.unwrap(); + return Some(helper.funclet_br(self, bx, target, mergeable_succ)); } + + let layout = bx.layout_of(ty); + + let msg_str = with_no_visible_paths!({ + with_no_trimmed_paths!({ + if layout.is_uninhabited() { + // Use this error even for the other intrinsics as it is more precise. + format!("attempted to instantiate uninhabited type `{ty}`") + } else if requirement == ValidityRequirement::Zero { + format!("attempted to zero-initialize type `{ty}`, which is invalid") + } else { + format!("attempted to leave type `{ty}` uninitialized, which is invalid") + } + }) + }); + let msg = bx.const_str(&msg_str); + + // Obtain the panic entry point. + let (fn_abi, llfn, instance) = + common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind); + + // Codegen the actual panic invoke/call. + Some(helper.do_call( + self, + bx, + fn_abi, + llfn, + &[msg.0, msg.1], + target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)), + unwind, + &[], + Some(instance), + mergeable_succ, + )) } fn codegen_call_terminator( -- cgit 1.4.1-3-g733a5 From 1e7c4377de7d80786151b355307e104709904b31 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Mon, 26 May 2025 15:37:45 +0200 Subject: ci: move dist-x86_64-linux job to codebuild --- src/ci/github-actions/jobs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 1d175bd97e6..f444e09c311 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -132,7 +132,7 @@ try: - name: dist-x86_64-linux env: CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-16c + <<: *job-linux-36c-codebuild # Main CI jobs that have to be green to merge a commit into master # These jobs automatically inherit envs.auto, to avoid repeating @@ -228,7 +228,7 @@ auto: - name: dist-x86_64-linux env: CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-16c + <<: *job-linux-36c-codebuild - name: dist-x86_64-linux-alt env: -- cgit 1.4.1-3-g733a5 From 7aef56d9b938a0df077c346007921497c092fdc9 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 26 May 2025 15:06:36 -0400 Subject: Call out possibility of invariant result --- library/core/src/marker/variance.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/core/src/marker/variance.rs b/library/core/src/marker/variance.rs index 235f8a3bb79..f9638fea225 100644 --- a/library/core/src/marker/variance.rs +++ b/library/core/src/marker/variance.rs @@ -131,6 +131,8 @@ phantom_lifetime! { /// /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance /// + /// Note: If `'a` is otherwise contravariant or invariant, the resulting type is invariant. + /// /// ## Layout /// /// For all `'a`, the following are guaranteed: @@ -146,6 +148,8 @@ phantom_lifetime! { /// /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance /// + /// Note: If `'a` is otherwise covariant or invariant, the resulting type is invariant. + /// /// ## Layout /// /// For all `'a`, the following are guaranteed: @@ -180,6 +184,8 @@ phantom_type! { /// /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance /// + /// Note: If `T` is otherwise contravariant or invariant, the resulting type is invariant. + /// /// ## Layout /// /// For all `T`, the following are guaranteed: @@ -196,6 +202,8 @@ phantom_type! { /// /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance /// + /// Note: If `T` is otherwise covariant or invariant, the resulting type is invariant. + /// /// ## Layout /// /// For all `T`, the following are guaranteed: -- cgit 1.4.1-3-g733a5 From c6c2fde737e5d6730cc7135afd841a0afed6096e Mon Sep 17 00:00:00 2001 From: Marcelo Domínguez Date: Mon, 26 May 2025 19:47:42 +0000 Subject: Minor macro docs fixes --- library/core/src/macros/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 99a4ab52b6c..fac1b1ae612 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1519,8 +1519,9 @@ pub(crate) mod builtin { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } - /// the derivative of a given function in the forward mode of differentiation. - /// It may only be applied to a function. + /// This macro uses forward-mode automatic differentiation to generate a new function. + /// It may only be applied to a function. The new function will compute the derivative + /// of the function to which the macro was applied. /// /// The expected usage syntax is: /// `#[autodiff_forward(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` @@ -1537,9 +1538,9 @@ pub(crate) mod builtin { /* compiler built-in */ } - /// Automatic Differentiation macro which allows generating a new function to compute - /// the derivative of a given function in the reverse mode of differentiation. - /// It may only be applied to a function. + /// This macro uses reverse-mode automatic differentiation to generate a new function. + /// It may only be applied to a function. The new function will compute the derivative + /// of the function to which the macro was applied. /// /// The expected usage syntax is: /// `#[autodiff_reverse(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` -- cgit 1.4.1-3-g733a5 From c56efaedfa0a28d842365c6c98a11af591eab1a5 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 23 May 2025 14:46:38 +0000 Subject: add additional `TypeFlags` fast paths --- .../src/infer/canonical/canonicalizer.rs | 4 ++++ compiler/rustc_infer/src/infer/resolve.rs | 8 +++++++ compiler/rustc_middle/src/ty/erase_regions.rs | 8 +++++++ compiler/rustc_middle/src/ty/fold.rs | 4 ++++ compiler/rustc_middle/src/ty/predicate.rs | 2 ++ compiler/rustc_middle/src/ty/structural_impls.rs | 27 +++++++++++++++++++++- .../rustc_next_trait_solver/src/canonicalizer.rs | 4 ++++ compiler/rustc_next_trait_solver/src/resolve.rs | 20 ++++++++++++++-- .../src/solve/eval_ctxt/canonical.rs | 11 ++++----- .../src/solve/eval_ctxt/mod.rs | 16 +++++++++++++ .../src/solve/inspect/analyse.rs | 9 ++++---- compiler/rustc_type_ir/src/binder.rs | 8 +++++++ compiler/rustc_type_ir/src/fold.rs | 8 +++++++ compiler/rustc_type_ir/src/inherent.rs | 12 ++++++++++ compiler/rustc_type_ir/src/interner.rs | 4 ++-- compiler/rustc_type_ir/src/visit.rs | 4 ++-- 16 files changed, 131 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 0b543f091f7..060447ba720 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -497,6 +497,10 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { if p.flags().intersects(self.needs_canonical_flags) { p.super_fold_with(self) } else { p } } + + fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { + if c.flags().intersects(self.needs_canonical_flags) { c.super_fold_with(self) } else { c } + } } impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 4b0ace8c554..a95f24b5b95 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -55,6 +55,14 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticVarResolver<'a, 'tcx> { ct.super_fold_with(self) } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if !p.has_non_region_infer() { p } else { p.super_fold_with(self) } + } + + fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { + if !c.has_non_region_infer() { c } else { c.super_fold_with(self) } + } } /// The opportunistic region resolver opportunistically resolves regions diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 45a0b1288db..f4fead7e952 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -86,4 +86,12 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { p } } + + fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { + if c.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { + c.super_fold_with(self) + } else { + c + } + } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 8d6871d2f1f..b2057fa36d7 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -177,6 +177,10 @@ where fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } } + + fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { + if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c } + } } impl<'tcx> TyCtxt<'tcx> { diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 551d816941b..bc2ac42b6b1 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -238,6 +238,8 @@ impl<'tcx> Clause<'tcx> { } } +impl<'tcx> rustc_type_ir::inherent::Clauses> for ty::Clauses<'tcx> {} + #[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)] impl<'tcx> ExistentialPredicate<'tcx> { /// Compares via an ordering that will not change if modules are reordered or other changes are diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 58f7bc75054..def7ad6cb3a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -570,6 +570,19 @@ impl<'tcx> TypeFoldable> for ty::Clause<'tcx> { } } +impl<'tcx> TypeFoldable> for ty::Clauses<'tcx> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + folder.try_fold_clauses(self) + } + + fn fold_with>>(self, folder: &mut F) -> Self { + folder.fold_clauses(self) + } +} + impl<'tcx> TypeVisitable> for ty::Predicate<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(*self) @@ -615,6 +628,19 @@ impl<'tcx> TypeSuperVisitable> for ty::Clauses<'tcx> { } } +impl<'tcx> TypeSuperFoldable> for ty::Clauses<'tcx> { + fn try_super_fold_with>>( + self, + folder: &mut F, + ) -> Result { + ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_clauses(v)) + } + + fn super_fold_with>>(self, folder: &mut F) -> Self { + ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v)) + } +} + impl<'tcx> TypeFoldable> for ty::Const<'tcx> { fn try_fold_with>>( self, @@ -775,7 +801,6 @@ macro_rules! list_fold { } list_fold! { - ty::Clauses<'tcx> : mk_clauses, &'tcx ty::List> : mk_poly_existential_predicates, &'tcx ty::List> : mk_place_elems, &'tcx ty::List> : mk_patterns, diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index addeb3e2b78..1aced3f261b 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -572,4 +572,8 @@ impl, I: Interner> TypeFolder for Canonicaliz fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { if p.flags().intersects(NEEDS_CANONICAL) { p.super_fold_with(self) } else { p } } + + fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + if c.flags().intersects(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c } + } } diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index 39abec2d7d8..c3c57eccd6e 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -11,7 +11,7 @@ use crate::delegate::SolverDelegate; // EAGER RESOLUTION /// Resolves ty, region, and const vars to their inferred values or their root vars. -pub struct EagerResolver<'a, D, I = ::Interner> +struct EagerResolver<'a, D, I = ::Interner> where D: SolverDelegate, I: Interner, @@ -22,8 +22,20 @@ where cache: DelayedMap, } +pub fn eager_resolve_vars>( + delegate: &D, + value: T, +) -> T { + if value.has_infer() { + let mut folder = EagerResolver::new(delegate); + value.fold_with(&mut folder) + } else { + value + } +} + impl<'a, D: SolverDelegate> EagerResolver<'a, D> { - pub fn new(delegate: &'a D) -> Self { + fn new(delegate: &'a D) -> Self { EagerResolver { delegate, cache: Default::default() } } } @@ -90,4 +102,8 @@ impl, I: Interner> TypeFolder for EagerResolv fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { if p.has_infer() { p.super_fold_with(self) } else { p } } + + fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + if c.has_infer() { c.super_fold_with(self) } else { c } + } } 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 455a178595b..2828b13f036 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 @@ -22,7 +22,7 @@ use tracing::{debug, instrument, trace}; use crate::canonicalizer::Canonicalizer; use crate::delegate::SolverDelegate; -use crate::resolve::EagerResolver; +use crate::resolve::eager_resolve_vars; use crate::solve::eval_ctxt::CurrentGoalKind; use crate::solve::{ CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, ExternalConstraintsData, Goal, @@ -61,8 +61,7 @@ where // so we only canonicalize the lookup table and ignore // duplicate entries. let opaque_types = self.delegate.clone_opaque_types_lookup_table(); - let (goal, opaque_types) = - (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate)); + let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types)); let mut orig_values = Default::default(); let canonical = Canonicalizer::canonicalize_input( @@ -157,8 +156,8 @@ where let external_constraints = self.compute_external_query_constraints(certainty, normalization_nested_goals); - let (var_values, mut external_constraints) = (self.var_values, external_constraints) - .fold_with(&mut EagerResolver::new(self.delegate)); + let (var_values, mut external_constraints) = + eager_resolve_vars(self.delegate, (self.var_values, external_constraints)); // Remove any trivial or duplicated region constraints once we've resolved regions let mut unique = HashSet::default(); @@ -469,7 +468,7 @@ where { let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) }; let state = inspect::State { var_values, data }; - let state = state.fold_with(&mut EagerResolver::new(delegate)); + let state = eager_resolve_vars(delegate, state); Canonicalizer::canonicalize_response(delegate, max_input_universe, &mut vec![], state) } 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 dfabb94ebfc..926b5c8123a 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 @@ -848,6 +848,22 @@ where } } } + + fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { + if p.has_non_region_infer() || p.has_placeholders() { + p.super_visit_with(self) + } else { + ControlFlow::Continue(()) + } + } + + fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result { + if c.has_non_region_infer() || c.has_placeholders() { + c.super_visit_with(self) + } else { + ControlFlow::Continue(()) + } + } } let mut visitor = ContainsTermOrNotNameable { diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 9795655e842..84808dc5b7e 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -15,9 +15,9 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_macros::extension; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult}; -use rustc_middle::ty::{TyCtxt, TypeFoldable, VisitorResult, try_visit}; +use rustc_middle::ty::{TyCtxt, VisitorResult, try_visit}; use rustc_middle::{bug, ty}; -use rustc_next_trait_solver::resolve::EagerResolver; +use rustc_next_trait_solver::resolve::eager_resolve_vars; use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state}; use rustc_next_trait_solver::solve::{GenerateProofTree, MaybeCause, SolverDelegateEvalExt as _}; use rustc_span::{DUMMY_SP, Span}; @@ -187,8 +187,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let _ = term_hack.constrain(infcx, span, param_env); } - let opt_impl_args = - opt_impl_args.map(|impl_args| impl_args.fold_with(&mut EagerResolver::new(infcx))); + let opt_impl_args = opt_impl_args.map(|impl_args| eager_resolve_vars(infcx, impl_args)); let goals = instantiated_goals .into_iter() @@ -392,7 +391,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { infcx, depth, orig_values, - goal: uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)), + goal: eager_resolve_vars(infcx, uncanonicalized_goal), result, evaluation_kind: evaluation.kind, normalizes_to_term_hack, diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 000cf1e1fd8..1b056b887db 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -711,6 +711,14 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { c.super_fold_with(self) } } + + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { + if p.has_param() { p.super_fold_with(self) } else { p } + } + + fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + if c.has_param() { c.super_fold_with(self) } else { c } + } } impl<'a, I: Interner> ArgFolder<'a, I> { diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index ce1188070ca..a5eb8699e5f 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -152,6 +152,10 @@ pub trait TypeFolder: Sized { fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { p.super_fold_with(self) } + + fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + c.super_fold_with(self) + } } /// This trait is implemented for every folding traversal. There is a fold @@ -190,6 +194,10 @@ pub trait FallibleTypeFolder: Sized { fn try_fold_predicate(&mut self, p: I::Predicate) -> Result { p.try_super_fold_with(self) } + + fn try_fold_clauses(&mut self, c: I::Clauses) -> Result { + c.try_super_fold_with(self) + } } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index ee4a8096462..b3b49b2c6ec 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -510,6 +510,18 @@ pub trait Clause>: fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder>) -> Self; } +pub trait Clauses>: + Copy + + Debug + + Hash + + Eq + + TypeSuperVisitable + + TypeSuperFoldable + + Flags + + SliceLike +{ +} + /// Common capabilities of placeholder kinds pub trait PlaceholderLike: Copy + Debug + Hash + Eq { fn universe(self) -> ty::UniverseIndex; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 7e88114df46..a9917192144 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -12,7 +12,7 @@ use crate::ir_print::IrPrint; use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult}; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; +use crate::visit::{Flags, TypeVisitable}; use crate::{self as ty, search_graph}; #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")] @@ -146,7 +146,7 @@ pub trait Interner: type ParamEnv: ParamEnv; type Predicate: Predicate; type Clause: Clause; - type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; + type Clauses: Clauses; fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R; diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index ccb84e25911..fc3864dd5ae 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -120,8 +120,8 @@ pub trait TypeVisitor: Sized { p.super_visit_with(self) } - fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result { - p.super_visit_with(self) + fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result { + c.super_visit_with(self) } fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result { -- cgit 1.4.1-3-g733a5 From 0830ce036f92673fa54a06cc4eacb47426850d33 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 26 May 2025 11:00:29 +0000 Subject: assert we never incorrectly canonicalize envs --- compiler/rustc_next_trait_solver/src/canonicalizer.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 1aced3f261b..e5ca2bda459 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -574,6 +574,13 @@ impl, I: Interner> TypeFolder for Canonicaliz } fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + match self.canonicalize_mode { + CanonicalizeMode::Input { keep_static: true } + | CanonicalizeMode::Response { max_input_universe: _ } => {} + CanonicalizeMode::Input { keep_static: false } => { + panic!("erasing 'static in env") + } + } if c.flags().intersects(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c } } } -- cgit 1.4.1-3-g733a5 From 1b7a927d846ae02c3a403be0eb47714c557c49b4 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Mon, 26 May 2025 22:27:20 +0200 Subject: ci: move tests from x86_64-gnu-llvm-19 job to aarch64 --- .../host-aarch64/aarch64-gnu-llvm-19/Dockerfile | 58 ++++++++++++++++++++++ src/ci/docker/scripts/x86_64-gnu-llvm.sh | 4 +- src/ci/github-actions/jobs.yml | 12 ++++- tests/debuginfo/by-value-non-immediate-argument.rs | 1 + tests/run-make/mte-ffi/bar.h | 2 + tests/run-make/mte-ffi/bar_float.c | 4 +- tests/run-make/mte-ffi/bar_int.c | 2 +- tests/run-make/mte-ffi/bar_string.c | 3 +- 8 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile new file mode 100644 index 00000000000..2f9d0010573 --- /dev/null +++ b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile @@ -0,0 +1,58 @@ +FROM ubuntu:24.10 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + bzip2 \ + g++ \ + 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/* + +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=aarch64-unknown-linux-gnu \ + --llvm-root=/usr/lib/llvm-19 \ + --enable-llvm-link-shared \ + --set rust.randomize-layout=true \ + --set rust.thin-lto-import-instr-limit=10 + +COPY scripts/shared.sh /scripts/ + +ARG SCRIPT_ARG + +COPY scripts/stage_2_test_set1.sh /tmp/ +COPY scripts/stage_2_test_set2.sh /tmp/ + +ENV SCRIPT "/tmp/${SCRIPT_ARG}" diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh index e0435a3ff5c..5fa17d954c3 100755 --- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh +++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh @@ -2,8 +2,8 @@ set -ex -# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. -../x.py --stage 2 test --skip src/tools/tidy +# NOTE: intentionally uses `x`, and `x.ps1` to make sure they work on Linux. +# Make sure that `x.py` is tested elsewhere. # Run the `mir-opt` tests again but this time for a 32-bit target. # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 1d175bd97e6..d7207edb7f9 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -121,7 +121,17 @@ pr: env: ENABLE_GCC_CODEGEN: "1" DOCKER_SCRIPT: x86_64-gnu-llvm.sh - <<: *job-linux-16c + <<: *job-linux-4c + - name: aarch64-gnu-llvm-19-1 + env: + IMAGE: aarch64-gnu-llvm-19 + DOCKER_SCRIPT: stage_2_test_set1.sh + <<: *job-aarch64-linux-8c + - name: aarch64-gnu-llvm-19-2 + env: + IMAGE: aarch64-gnu-llvm-19 + DOCKER_SCRIPT: stage_2_test_set2.sh + <<: *job-aarch64-linux - name: x86_64-gnu-tools <<: *job-linux-36c-codebuild diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs index 192f6efe7db..5233b95f1f4 100644 --- a/tests/debuginfo/by-value-non-immediate-argument.rs +++ b/tests/debuginfo/by-value-non-immediate-argument.rs @@ -2,6 +2,7 @@ //@ min-gdb-version: 13.0 //@ compile-flags:-g //@ ignore-windows-gnu: #128973 +//@ ignore-aarch64-unknown-linux-gnu (gdb tries to read from 0x0; FIXME: #128973) // === GDB TESTS =================================================================================== diff --git a/tests/run-make/mte-ffi/bar.h b/tests/run-make/mte-ffi/bar.h index a2292ae02a3..9b030c618d1 100644 --- a/tests/run-make/mte-ffi/bar.h +++ b/tests/run-make/mte-ffi/bar.h @@ -1,3 +1,5 @@ +// FIXME(#141600) the mte-ffi test doesn't fail in aarch64-gnu + #ifndef __BAR_H #define __BAR_H diff --git a/tests/run-make/mte-ffi/bar_float.c b/tests/run-make/mte-ffi/bar_float.c index a1590f62765..acc2f5d9266 100644 --- a/tests/run-make/mte-ffi/bar_float.c +++ b/tests/run-make/mte-ffi/bar_float.c @@ -3,9 +3,9 @@ #include #include "bar.h" -extern void foo(char*); +extern void foo(float*); -void bar(char *ptr) { +void bar(float *ptr) { if (((uintptr_t)ptr >> 56) != 0x1f) { fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); exit(1); diff --git a/tests/run-make/mte-ffi/bar_int.c b/tests/run-make/mte-ffi/bar_int.c index d1c79e95dc9..c92e765302c 100644 --- a/tests/run-make/mte-ffi/bar_int.c +++ b/tests/run-make/mte-ffi/bar_int.c @@ -5,7 +5,7 @@ extern void foo(unsigned int *); -void bar(char *ptr) { +void bar(unsigned int *ptr) { if (((uintptr_t)ptr >> 56) != 0x1f) { fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); exit(1); diff --git a/tests/run-make/mte-ffi/bar_string.c b/tests/run-make/mte-ffi/bar_string.c index 5669ffd6695..8e1202f6fd1 100644 --- a/tests/run-make/mte-ffi/bar_string.c +++ b/tests/run-make/mte-ffi/bar_string.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "bar.h" extern void foo(char*); @@ -32,7 +33,7 @@ int main(void) // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be), // and a different value in the ignored top 4 bits. - ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56); + ptr = (char *)((uintptr_t)ptr | 0x1fl << 56); if (mte_enabled()) { set_tag(ptr); -- cgit 1.4.1-3-g733a5 From df09feddfa7900c841877faa3cda86bfc08d9610 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 May 2025 16:39:59 +1000 Subject: Remove `DropNodeKey::kind`. It's not needed, because `next` and `local` fields uniquely identify the drop. This is a ~2% speed win on the very large program in #134404, and it's also a tiny bit simpler. --- compiler/rustc_mir_build/src/builder/scope.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 2a30777e98c..bc39ad6b267 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -230,7 +230,6 @@ struct DropNode { struct DropNodeKey { next: DropIdx, local: Local, - kind: DropKind, } impl Scope { @@ -291,7 +290,7 @@ impl DropTree { let drops = &mut self.drops; *self .existing_drops_map - .entry(DropNodeKey { next, local: data.local, kind: data.kind }) + .entry(DropNodeKey { next, local: data.local }) // Create a new node, and also add its index to the map. .or_insert_with(|| drops.push(DropNode { data, next })) } -- cgit 1.4.1-3-g733a5 From bf4532c05d2537c091de6787b8bb80e2cd24cd63 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 May 2025 05:46:03 +1000 Subject: Rename `DropTree::drops` as `DropTree::drop_nodes`. Because `Scope` also has a field named `drops`, and I found having two fields with the same name made this code harder to read. --- compiler/rustc_mir_build/src/builder/scope.rs | 80 +++++++++++++++------------ 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index bc39ad6b267..d7900cb0845 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -209,7 +209,7 @@ const ROOT_NODE: DropIdx = DropIdx::ZERO; #[derive(Debug)] struct DropTree { /// Nodes in the drop tree, containing drop data and a link to the next node. - drops: IndexVec, + drop_nodes: IndexVec, /// Map for finding the index of an existing node, given its contents. existing_drops_map: FxHashMap, /// Edges into the `DropTree` that need to be added once it's lowered. @@ -277,8 +277,8 @@ impl DropTree { let fake_source_info = SourceInfo::outermost(DUMMY_SP); let fake_data = DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage }; - let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]); - Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() } + let drop_nodes = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]); + Self { drop_nodes, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() } } /// Adds a node to the drop tree, consisting of drop data and the index of @@ -287,12 +287,12 @@ impl DropTree { /// If there is already an equivalent node in the tree, nothing is added, and /// that node's index is returned. Otherwise, the new node's index is returned. fn add_drop(&mut self, data: DropData, next: DropIdx) -> DropIdx { - let drops = &mut self.drops; + let drop_nodes = &mut self.drop_nodes; *self .existing_drops_map .entry(DropNodeKey { next, local: data.local }) // Create a new node, and also add its index to the map. - .or_insert_with(|| drops.push(DropNode { data, next })) + .or_insert_with(|| drop_nodes.push(DropNode { data, next })) } /// Registers `from` as an entry point to this drop tree, at `to`. @@ -300,7 +300,7 @@ impl DropTree { /// During [`Self::build_mir`], `from` will be linked to the corresponding /// block within the drop tree. fn add_entry_point(&mut self, from: BasicBlock, to: DropIdx) { - debug_assert!(to < self.drops.next_index()); + debug_assert!(to < self.drop_nodes.next_index()); self.entry_points.push((to, from)); } @@ -340,10 +340,10 @@ impl DropTree { Own, } - let mut blocks = IndexVec::from_elem(None, &self.drops); + let mut blocks = IndexVec::from_elem(None, &self.drop_nodes); blocks[ROOT_NODE] = root_node; - let mut needs_block = IndexVec::from_elem(Block::None, &self.drops); + let mut needs_block = IndexVec::from_elem(Block::None, &self.drop_nodes); if root_node.is_some() { // In some cases (such as drops for `continue`) the root node // already has a block. In this case, make sure that we don't @@ -355,7 +355,7 @@ impl DropTree { let entry_points = &mut self.entry_points; entry_points.sort(); - for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() { + for (drop_idx, drop_node) in self.drop_nodes.iter_enumerated().rev() { if entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) { let block = *blocks[drop_idx].get_or_insert_with(|| T::make_block(cfg)); needs_block[drop_idx] = Block::Own; @@ -395,7 +395,7 @@ impl DropTree { cfg: &mut CFG<'tcx>, blocks: &IndexSlice>, ) { - for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() { + for (drop_idx, drop_node) in self.drop_nodes.iter_enumerated().rev() { let Some(block) = blocks[drop_idx] else { continue }; match drop_node.data.kind { DropKind::Value => { @@ -828,9 +828,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // `unwind_to` should drop the value that we're about to // schedule. If dropping this value panics, then we continue // with the *next* value on the unwind path. - debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local); - debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind); - unwind_to = unwind_drops.drops[unwind_to].next; + debug_assert_eq!( + unwind_drops.drop_nodes[unwind_to].data.local, + drop_data.local + ); + debug_assert_eq!( + unwind_drops.drop_nodes[unwind_to].data.kind, + drop_data.kind + ); + unwind_to = unwind_drops.drop_nodes[unwind_to].next; let mut unwind_entry_point = unwind_to; @@ -1550,14 +1556,14 @@ where // // We adjust this BEFORE we create the drop (e.g., `drops[n]`) // because `drops[n]` should unwind to `drops[n-1]`. - debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local); - debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind); - unwind_to = unwind_drops.drops[unwind_to].next; + debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.local, drop_data.local); + debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind); + unwind_to = unwind_drops.drop_nodes[unwind_to].next; if let Some(idx) = dropline_to { - debug_assert_eq!(coroutine_drops.drops[idx].data.local, drop_data.local); - debug_assert_eq!(coroutine_drops.drops[idx].data.kind, drop_data.kind); - dropline_to = Some(coroutine_drops.drops[idx].next); + debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.local, drop_data.local); + debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.kind, drop_data.kind); + dropline_to = Some(coroutine_drops.drop_nodes[idx].next); } // If the operand has been moved, and we are not on an unwind @@ -1597,9 +1603,12 @@ where // cases we emit things ALSO on the unwind path, so we need to adjust // `unwind_to` in that case. if storage_dead_on_unwind { - debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local); - debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind); - unwind_to = unwind_drops.drops[unwind_to].next; + debug_assert_eq!( + unwind_drops.drop_nodes[unwind_to].data.local, + drop_data.local + ); + debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind); + unwind_to = unwind_drops.drop_nodes[unwind_to].next; } // If the operand has been moved, and we are not on an unwind @@ -1628,14 +1637,17 @@ where // the storage-dead has completed, we need to adjust the `unwind_to` pointer // so that any future drops we emit will not register storage-dead. if storage_dead_on_unwind { - debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local); - debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind); - unwind_to = unwind_drops.drops[unwind_to].next; + debug_assert_eq!( + unwind_drops.drop_nodes[unwind_to].data.local, + drop_data.local + ); + debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind); + unwind_to = unwind_drops.drop_nodes[unwind_to].next; } if let Some(idx) = dropline_to { - debug_assert_eq!(coroutine_drops.drops[idx].data.local, drop_data.local); - debug_assert_eq!(coroutine_drops.drops[idx].data.kind, drop_data.kind); - dropline_to = Some(coroutine_drops.drops[idx].next); + debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.local, drop_data.local); + debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.kind, drop_data.kind); + dropline_to = Some(coroutine_drops.drop_nodes[idx].next); } // Only temps and vars need their storage dead. assert!(local.index() > arg_count); @@ -1662,10 +1674,10 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { let is_coroutine = self.coroutine.is_some(); // Link the exit drop tree to unwind drop tree. - if drops.drops.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) { + if drops.drop_nodes.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) { let unwind_target = self.diverge_cleanup_target(else_scope, span); let mut unwind_indices = IndexVec::from_elem_n(unwind_target, 1); - for (drop_idx, drop_node) in drops.drops.iter_enumerated().skip(1) { + for (drop_idx, drop_node) in drops.drop_nodes.iter_enumerated().skip(1) { match drop_node.data.kind { DropKind::Storage | DropKind::ForLint => { if is_coroutine { @@ -1694,13 +1706,13 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { } // Link the exit drop tree to dropline drop tree (coroutine drop path) for async drops if is_coroutine - && drops.drops.iter().any(|DropNode { data, next: _ }| { + && drops.drop_nodes.iter().any(|DropNode { data, next: _ }| { data.kind == DropKind::Value && self.is_async_drop(data.local) }) { let dropline_target = self.diverge_dropline_target(else_scope, span); let mut dropline_indices = IndexVec::from_elem_n(dropline_target, 1); - for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) { + for (drop_idx, drop_data) in drops.drop_nodes.iter_enumerated().skip(1) { match drop_data.data.kind { DropKind::Storage | DropKind::ForLint => { let coroutine_drop = self @@ -1768,11 +1780,11 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { // prevent drop elaboration from creating drop flags that would have // to be captured by the coroutine. I'm not sure how important this // optimization is, but it is here. - for (drop_idx, drop_node) in drops.drops.iter_enumerated() { + for (drop_idx, drop_node) in drops.drop_nodes.iter_enumerated() { if let DropKind::Value = drop_node.data.kind && let Some(bb) = blocks[drop_idx] { - debug_assert!(drop_node.next < drops.drops.next_index()); + debug_assert!(drop_node.next < drops.drop_nodes.next_index()); drops.entry_points.push((drop_node.next, bb)); } } -- cgit 1.4.1-3-g733a5 From 84bb48fc886d5de72c86fb56c11f8586ca465647 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 May 2025 05:48:40 +1000 Subject: Factor out some repeated code in `build_exit_tree`. --- compiler/rustc_mir_build/src/builder/scope.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index d7900cb0845..28d72f73155 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -1713,28 +1713,22 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { let dropline_target = self.diverge_dropline_target(else_scope, span); let mut dropline_indices = IndexVec::from_elem_n(dropline_target, 1); for (drop_idx, drop_data) in drops.drop_nodes.iter_enumerated().skip(1) { + let coroutine_drop = self + .scopes + .coroutine_drops + .add_drop(drop_data.data, dropline_indices[drop_data.next]); match drop_data.data.kind { - DropKind::Storage | DropKind::ForLint => { - let coroutine_drop = self - .scopes - .coroutine_drops - .add_drop(drop_data.data, dropline_indices[drop_data.next]); - dropline_indices.push(coroutine_drop); - } + DropKind::Storage | DropKind::ForLint => {} DropKind::Value => { - let coroutine_drop = self - .scopes - .coroutine_drops - .add_drop(drop_data.data, dropline_indices[drop_data.next]); if self.is_async_drop(drop_data.data.local) { self.scopes.coroutine_drops.add_entry_point( blocks[drop_idx].unwrap(), dropline_indices[drop_data.next], ); } - dropline_indices.push(coroutine_drop); } } + dropline_indices.push(coroutine_drop); } } blocks[ROOT_NODE].map(BasicBlock::unit) -- cgit 1.4.1-3-g733a5 From ec8baa5d43903a6f39ebc36370120db129a52deb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 May 2025 05:54:13 +1000 Subject: Avoid `fold`/`flat_map`. This pattern of iterating over scopes and drops occurs multiple times in this file, with slight variations. All of them use `for` loops except this one. This commits changes it for consistency. --- compiler/rustc_mir_build/src/builder/scope.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 28d72f73155..67988f1fcbc 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -725,11 +725,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { drops }; - let drop_idx = self.scopes.scopes[scope_index + 1..] - .iter() - .flat_map(|scope| &scope.drops) - .fold(ROOT_NODE, |drop_idx, &drop| drops.add_drop(drop, drop_idx)); - + let mut drop_idx = ROOT_NODE; + for scope in &self.scopes.scopes[scope_index + 1..] { + for drop in &scope.drops { + drop_idx = drops.add_drop(*drop, drop_idx); + } + } drops.add_entry_point(block, drop_idx); // `build_drop_trees` doesn't have access to our source_info, so we -- cgit 1.4.1-3-g733a5 From 7baa85d16b05bcb6bc173471f5e6b8263057bed5 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 27 May 2025 06:44:34 +0300 Subject: Fix inference of `AsyncFnX` return type --- .../rust-analyzer/crates/hir-ty/src/chalk_db.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/display.rs | 2 + .../crates/hir-ty/src/infer/closure.rs | 56 ++++++++++++++++++---- .../crates/hir-ty/src/tests/traits.rs | 27 +++++++++++ .../rust-analyzer/crates/hir-ty/src/traits.rs | 5 ++ 5 files changed, 81 insertions(+), 11 deletions(-) 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 cd799c03ddf..22b96b55cbb 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 @@ -259,7 +259,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { } fn well_known_trait_id( &self, - well_known_trait: rust_ir::WellKnownTrait, + well_known_trait: WellKnownTrait, ) -> Option> { let lang_attr = lang_item_from_well_known_trait(well_known_trait); let trait_ = lang_attr.resolve_trait(self.db, self.krate)?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index f0989d9de91..f210dd8799f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -1463,6 +1463,8 @@ impl HirDisplay for Ty { } if f.closure_style == ClosureStyle::RANotation || !sig.ret().is_unit() { write!(f, " -> ")?; + // FIXME: We display `AsyncFn` as `-> impl Future`, but this is hard to fix because + // we don't have a trait environment here, required to normalize `::Output`. sig.ret().hir_fmt(f)?; } } else { 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 800897c6fc3..bd57ca89162 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 @@ -38,7 +38,7 @@ use crate::{ infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever}, make_binders, mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, - to_chalk_trait_id, + to_assoc_type_id, to_chalk_trait_id, traits::FnTrait, utils::{self, elaborate_clause_supertraits}, }; @@ -245,7 +245,7 @@ impl InferenceContext<'_> { } fn deduce_closure_kind_from_predicate_clauses( - &self, + &mut self, expected_ty: &Ty, clauses: impl DoubleEndedIterator, closure_kind: ClosureKind, @@ -378,7 +378,7 @@ impl InferenceContext<'_> { } fn deduce_sig_from_projection( - &self, + &mut self, closure_kind: ClosureKind, projection_ty: &ProjectionTy, projected_ty: &Ty, @@ -392,13 +392,16 @@ impl InferenceContext<'_> { // For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits, // for closures and async closures, respectively. - match closure_kind { - ClosureKind::Closure | ClosureKind::Async - if self.fn_trait_kind_from_trait_id(trait_).is_some() => - { - self.extract_sig_from_projection(projection_ty, projected_ty) - } - _ => None, + let fn_trait_kind = self.fn_trait_kind_from_trait_id(trait_)?; + if !matches!(closure_kind, ClosureKind::Closure | ClosureKind::Async) { + return None; + } + if fn_trait_kind.is_async() { + // If the expected trait is `AsyncFn(...) -> X`, we don't know what the return type is, + // but we do know it must implement `Future`. + self.extract_async_fn_sig_from_projection(projection_ty, projected_ty) + } else { + self.extract_sig_from_projection(projection_ty, projected_ty) } } @@ -424,6 +427,39 @@ impl InferenceContext<'_> { ))) } + fn extract_async_fn_sig_from_projection( + &mut self, + projection_ty: &ProjectionTy, + projected_ty: &Ty, + ) -> Option> { + let arg_param_ty = projection_ty.substitution.as_slice(Interner)[1].assert_ty_ref(Interner); + + let TyKind::Tuple(_, input_tys) = arg_param_ty.kind(Interner) else { + return None; + }; + + let ret_param_future_output = projected_ty; + let ret_param_future = self.table.new_type_var(); + let future_output = + LangItem::FutureOutput.resolve_type_alias(self.db, self.resolver.krate())?; + let future_projection = crate::AliasTy::Projection(crate::ProjectionTy { + associated_ty_id: to_assoc_type_id(future_output), + substitution: Substitution::from1(Interner, ret_param_future.clone()), + }); + self.table.register_obligation( + crate::AliasEq { alias: future_projection, ty: ret_param_future_output.clone() } + .cast(Interner), + ); + + Some(FnSubst(Substitution::from_iter( + Interner, + input_tys.iter(Interner).map(|t| t.cast(Interner)).chain(Some(GenericArg::new( + Interner, + chalk_ir::GenericArgData::Ty(ret_param_future), + ))), + ))) + } + fn fn_trait_kind_from_trait_id(&self, trait_id: hir_def::TraitId) -> Option { FnTrait::from_lang_item(self.db.lang_attr(trait_id.into())?) } 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 2b527a4ae12..e5d1fbe9def 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 @@ -4903,3 +4903,30 @@ fn main() { "#]], ); } + +#[test] +fn async_fn_return_type() { + check_infer( + r#" +//- minicore: async_fn +fn foo R, R>(_: F) -> R { + loop {} +} + +fn main() { + foo(async move || ()); +} + "#, + expect![[r#" + 29..30 '_': F + 40..55 '{ loop {} }': R + 46..53 'loop {}': ! + 51..53 '{}': () + 67..97 '{ ...()); }': () + 73..76 'foo': fn foo impl Future, ()>(impl AsyncFn() -> impl Future) + 73..94 'foo(as...|| ())': () + 77..93 'async ... || ()': impl AsyncFn() -> impl Future + 91..93 '()': () + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index f9f8776cff7..7414b4fc607 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -291,4 +291,9 @@ impl FnTrait { pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option { self.lang_item().resolve_trait(db, krate) } + + #[inline] + pub(crate) fn is_async(self) -> bool { + matches!(self, FnTrait::AsyncFn | FnTrait::AsyncFnMut | FnTrait::AsyncFnOnce) + } } -- cgit 1.4.1-3-g733a5 From 68ff7f2878e25b99970957964696edd9a36271ed Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Mon, 26 May 2025 13:27:01 +0200 Subject: Make `Semantics<'db, DB>` support `Semantics<'db, dyn HirDatabase>`, by use of `DB: ?Sized` --- src/tools/rust-analyzer/crates/hir/src/semantics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 247d6406973..117d9c49200 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -147,7 +147,7 @@ impl TypeInfo { } /// Primary API to get semantic information, like types, from syntax trees. -pub struct Semantics<'db, DB> { +pub struct Semantics<'db, DB: ?Sized> { pub db: &'db DB, imp: SemanticsImpl<'db>, } -- cgit 1.4.1-3-g733a5 From 871327e9c7a6d44e233b31213858a224451afa74 Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 22 May 2025 17:44:10 -0500 Subject: rustdoc: linking to a local proc macro no longer warns fixes https://github.com/rust-lang/rust/issues/91274 Co-authored-by: Guillaume Gomez --- src/librustdoc/passes/collect_intra_doc_links.rs | 36 +++++++++++++++++----- .../rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs | 21 +++++++++++++ .../intra-doc/bad-link-to-proc-macro.stderr | 22 +++++++++++++ tests/rustdoc/intra-doc/link-to-proc-macro.rs | 13 ++++++++ 4 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs create mode 100644 tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr create mode 100644 tests/rustdoc/intra-doc/link-to-proc-macro.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f3e2138d1a5..b3a57ff3ff3 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -22,6 +22,7 @@ use rustc_resolve::rustdoc::{ MalformedGenerics, has_primitive_or_keyword_docs, prepare_to_doc_link_resolution, source_span_for_markdown_range, strip_generics_from_path, }; +use rustc_session::config::CrateType; use rustc_session::lint::Lint; use rustc_span::BytePos; use rustc_span::hygiene::MacroKind; @@ -1174,7 +1175,6 @@ impl LinkCollector<'_, '_> { #[allow(rustc::potential_query_instability)] pub(crate) fn resolve_ambiguities(&mut self) { let mut ambiguous_links = mem::take(&mut self.ambiguous_links); - for ((item_id, path_str), info_items) in ambiguous_links.iter_mut() { for info in info_items { info.resolved.retain(|(res, _)| match res { @@ -2232,15 +2232,35 @@ fn ambiguity_error( emit_error: bool, ) -> bool { let mut descrs = FxHashSet::default(); - let kinds = candidates + // proc macro can exist in multiple namespaces at once, so we need to compare `DefIds` + // to remove the candidate in the fn namespace. + let mut possible_proc_macro_id = None; + let is_proc_macro_crate = cx.tcx.crate_types() == &[CrateType::ProcMacro]; + let mut kinds = candidates .iter() - .map( - |(res, def_id)| { - if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res } - }, - ) - .filter(|res| descrs.insert(res.descr())) + .map(|(res, def_id)| { + let r = + if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res }; + if is_proc_macro_crate && let Res::Def(DefKind::Macro(_), id) = r { + possible_proc_macro_id = Some(id); + } + r + }) .collect::>(); + // In order to properly dedup proc macros, we have to do it in two passes: + // 1. Completing the full traversal to find the possible duplicate in the macro namespace, + // 2. Another full traversal to eliminate the candidate in the fn namespace. + // + // Thus, we have to do an iteration after collection is finished. + // + // As an optimization, we only deduplicate if we're in a proc-macro crate, + // and only if we already found something that looks like a proc macro. + if is_proc_macro_crate && let Some(macro_id) = possible_proc_macro_id { + kinds.retain(|res| !matches!(res, Res::Def(DefKind::Fn, fn_id) if macro_id == *fn_id)); + } + + kinds.retain(|res| descrs.insert(res.descr())); + if descrs.len() == 1 { // There is no way for users to disambiguate at this point, so better return the first // candidate and not show a warning. diff --git a/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs new file mode 100644 index 00000000000..b449465768e --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs @@ -0,0 +1,21 @@ +//@ compile-flags: --crate-type=proc-macro --document-private-items +#![deny(rustdoc::broken_intra_doc_links)] + +//! Link to [`m`]. +//~^ ERROR `m` is both a module and a macro + +// test a further edge case related to https://github.com/rust-lang/rust/issues/91274 + +// we need to make sure that when there is actually an ambiguity +// in a proc-macro crate, we print out a sensible error. +// because proc macro crates can't normally export modules, +// this can only happen in --document-private-items mode. + +extern crate proc_macro; + +mod m {} + +#[proc_macro] +pub fn m(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + input +} diff --git a/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr new file mode 100644 index 00000000000..09a5d26eded --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr @@ -0,0 +1,22 @@ +error: `m` is both a module and a macro + --> $DIR/bad-link-to-proc-macro.rs:4:15 + | +LL | //! Link to [`m`]. + | ^ ambiguous link + | +note: the lint level is defined here + --> $DIR/bad-link-to-proc-macro.rs:2:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to link to the module, prefix with `mod@` + | +LL | //! Link to [`mod@m`]. + | ++++ +help: to link to the macro, add an exclamation mark + | +LL | //! Link to [`m!`]. + | + + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc/intra-doc/link-to-proc-macro.rs b/tests/rustdoc/intra-doc/link-to-proc-macro.rs new file mode 100644 index 00000000000..6c289078db8 --- /dev/null +++ b/tests/rustdoc/intra-doc/link-to-proc-macro.rs @@ -0,0 +1,13 @@ +//@ compile-flags: --crate-type=proc-macro +//@ has 'foo/index.html' '//a[@href="macro.my_macro.html"]' 'my_macro' +//! Link to [`my_macro`]. +#![crate_name = "foo"] + +// regression test for https://github.com/rust-lang/rust/issues/91274 + +extern crate proc_macro; + +#[proc_macro] +pub fn my_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + input +} -- cgit 1.4.1-3-g733a5 From a83f8d02eaf36b36a7ed495e43b8bf891b6fc1af Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Fri, 2 May 2025 20:22:13 +0200 Subject: Always evaluate free lifetime-generic constants Co-authored-by: Michael Goulet --- compiler/rustc_hir_analysis/src/lib.rs | 4 +++- compiler/rustc_monomorphize/src/collector.rs | 2 +- tests/ui/generic-const-items/def-site-eval.fail.stderr | 4 ++-- tests/ui/generic-const-items/def-site-eval.rs | 7 +++---- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 010c6c376fe..a64c24f5455 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -203,7 +203,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.ensure_ok().eval_static_initializer(item_def_id); check::maybe_check_static_with_link_section(tcx, item_def_id); } - DefKind::Const if tcx.generics_of(item_def_id).is_empty() => { + DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() => { + // FIXME(generic_const_items): Passing empty instead of identity args is fishy but + // seems to be fine for now. Revisit this! let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty()); let cid = GlobalId { instance, promoted: None }; let typing_env = ty::TypingEnv::fully_monomorphized(); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b3d7eaf332b..1ee977a5457 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1483,7 +1483,7 @@ impl<'v> RootCollector<'_, 'v> { // But even just declaring them must collect the items they refer to // unless their generics require monomorphization. - if !self.tcx.generics_of(id.owner_id).requires_monomorphization(self.tcx) + if !self.tcx.generics_of(id.owner_id).own_requires_monomorphization() && let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id()) { collect_const_value(self.tcx, val, self.output); diff --git a/tests/ui/generic-const-items/def-site-eval.fail.stderr b/tests/ui/generic-const-items/def-site-eval.fail.stderr index fa07f385522..4e7d9d8154a 100644 --- a/tests/ui/generic-const-items/def-site-eval.fail.stderr +++ b/tests/ui/generic-const-items/def-site-eval.fail.stderr @@ -1,5 +1,5 @@ -error[E0080]: evaluation of `_::<'_>` failed - --> $DIR/def-site-eval.rs:14:20 +error[E0080]: evaluation of constant value failed + --> $DIR/def-site-eval.rs:13:20 | LL | const _<'_a>: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic diff --git a/tests/ui/generic-const-items/def-site-eval.rs b/tests/ui/generic-const-items/def-site-eval.rs index 3ed7f96aed0..b95e40c05d4 100644 --- a/tests/ui/generic-const-items/def-site-eval.rs +++ b/tests/ui/generic-const-items/def-site-eval.rs @@ -1,16 +1,15 @@ //! Test that we only evaluate free const items (their def site to be clear) //! whose generics don't require monomorphization. #![feature(generic_const_items)] -#![allow(incomplete_features)] +#![expect(incomplete_features)] //@ revisions: fail pass -//@[fail] build-fail (we require monomorphization) -//@[pass] build-pass (we require monomorphization) +//@[pass] check-pass const _<_T>: () = panic!(); const _: () = panic!(); #[cfg(fail)] -const _<'_a>: () = panic!(); //[fail]~ ERROR evaluation of `_::<'_>` failed +const _<'_a>: () = panic!(); //[fail]~ ERROR evaluation of constant value failed fn main() {} -- cgit 1.4.1-3-g733a5 From db21caf5ba1161d157e62956039f0ff2493454a9 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Fri, 2 May 2025 20:22:35 +0200 Subject: Drive-by: Delete dead TyCtxtEnsureOk::const_eval_poly --- compiler/rustc_middle/src/mir/interpret/queries.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 4a5c42c721c..97db45a70d7 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -9,7 +9,6 @@ use super::{ ReportedErrorInfo, }; use crate::mir; -use crate::query::TyCtxtEnsureOk; use crate::ty::{self, GenericArgs, TyCtxt, TypeVisitableExt}; impl<'tcx> TyCtxt<'tcx> { @@ -197,24 +196,3 @@ impl<'tcx> TyCtxt<'tcx> { } } } - -impl<'tcx> TyCtxtEnsureOk<'tcx> { - /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts - /// that can't take any generic arguments like const items or enum discriminants. If a - /// generic parameter is used within the constant `ErrorHandled::TooGeneric` will be returned. - #[instrument(skip(self), level = "debug")] - pub fn const_eval_poly(self, def_id: DefId) { - // In some situations def_id will have generic parameters within scope, but they aren't allowed - // to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters - // into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are - // encountered. - let args = GenericArgs::identity_for_item(self.tcx, def_id); - let instance = ty::Instance::new_raw(def_id, self.tcx.erase_regions(args)); - let cid = GlobalId { instance, promoted: None }; - let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id); - // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should - // improve caching of queries. - let inputs = self.tcx.erase_regions(typing_env.as_query_input(cid)); - self.eval_to_const_value_raw(inputs) - } -} -- cgit 1.4.1-3-g733a5 From e9080948c64cdb12014f11004a921a676fbc0964 Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 25 May 2025 23:14:59 +0800 Subject: consider glob imports in cfg suggestion --- compiler/rustc_expand/src/expand.rs | 6 +- compiler/rustc_resolve/src/diagnostics.rs | 50 ++++++++++++++++- tests/ui/cfg/diagnostics-reexport-2.rs | 61 +++++++++++++++++++++ tests/ui/cfg/diagnostics-reexport-2.stderr | 88 ++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 tests/ui/cfg/diagnostics-reexport-2.rs create mode 100644 tests/ui/cfg/diagnostics-reexport-2.stderr diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 81d4d59ee04..e5749ba96a6 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1319,10 +1319,10 @@ impl InvocationCollectorNode for P { let mut idents = Vec::new(); collect_use_tree_leaves(ut, &mut idents); - return idents; + idents + } else { + self.kind.ident().into_iter().collect() } - - if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] } } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d09750fa281..201b1c0a493 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -6,7 +6,7 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust; use rustc_attr_data_structures::{self as attr, Stability}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ @@ -2623,7 +2623,53 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; for &StrippedCfgItem { parent_module, ident, ref cfg } in symbols { - if parent_module != module || ident.name != *segment { + if ident.name != *segment { + continue; + } + + fn comes_from_same_module_for_glob( + r: &Resolver<'_, '_>, + parent_module: DefId, + module: DefId, + visited: &mut FxHashMap, + ) -> bool { + if let Some(&cached) = visited.get(&parent_module) { + // this branch is prevent from being called recursively infinity, + // because there has some cycles in globs imports, + // see more spec case at `tests/ui/cfg/diagnostics-reexport-2.rs#reexport32` + return cached; + } + visited.insert(parent_module, false); + let res = r.module_map.get(&parent_module).is_some_and(|m| { + for importer in m.glob_importers.borrow().iter() { + if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() + { + if next_parent_module == module + || comes_from_same_module_for_glob( + r, + next_parent_module, + module, + visited, + ) + { + return true; + } + } + } + false + }); + visited.insert(parent_module, res); + res + } + + let comes_from_same_module = parent_module == module + || comes_from_same_module_for_glob( + self, + parent_module, + module, + &mut Default::default(), + ); + if !comes_from_same_module { continue; } diff --git a/tests/ui/cfg/diagnostics-reexport-2.rs b/tests/ui/cfg/diagnostics-reexport-2.rs new file mode 100644 index 00000000000..f66b9ed99ee --- /dev/null +++ b/tests/ui/cfg/diagnostics-reexport-2.rs @@ -0,0 +1,61 @@ +// issue#141256 + +mod original { + #[cfg(false)] + //~^ NOTE the item is gated here + //~| NOTE the item is gated here + //~| NOTE the item is gated here + //~| NOTE the item is gated here + //~| NOTE the item is gated here + pub mod gated { + //~^ NOTE found an item that was configured out + //~| NOTE found an item that was configured out + //~| NOTE found an item that was configured out + //~| NOTE found an item that was configured out + //~| NOTE found an item that was configured out + pub fn foo() {} + } +} + +mod reexport { + pub use super::original::*; +} + +mod reexport2 { + pub use super::reexport::*; +} + +mod reexport30 { + pub use super::original::*; + pub use super::reexport31::*; +} + +mod reexport31 { + pub use super::reexport30::*; +} + +mod reexport32 { + pub use super::reexport30::*; +} + +fn main() { + reexport::gated::foo(); + //~^ ERROR failed to resolve: could not find `gated` in `reexport` + //~| NOTE could not find `gated` in `reexport` + + reexport2::gated::foo(); + //~^ ERROR failed to resolve: could not find `gated` in `reexport2` + //~| NOTE could not find `gated` in `reexport2` + + reexport30::gated::foo(); + //~^ ERROR failed to resolve: could not find `gated` in `reexport30` + //~| NOTE could not find `gated` in `reexport30` + + reexport31::gated::foo(); + //~^ ERROR failed to resolve: could not find `gated` in `reexport31` + //~| NOTE could not find `gated` in `reexport31` + + reexport32::gated::foo(); + //~^ ERROR failed to resolve: could not find `gated` in `reexport32` + //~| NOTE could not find `gated` in `reexport32` +} diff --git a/tests/ui/cfg/diagnostics-reexport-2.stderr b/tests/ui/cfg/diagnostics-reexport-2.stderr new file mode 100644 index 00000000000..95ac5a19b0b --- /dev/null +++ b/tests/ui/cfg/diagnostics-reexport-2.stderr @@ -0,0 +1,88 @@ +error[E0433]: failed to resolve: could not find `gated` in `reexport` + --> $DIR/diagnostics-reexport-2.rs:42:15 + | +LL | reexport::gated::foo(); + | ^^^^^ could not find `gated` in `reexport` + | +note: found an item that was configured out + --> $DIR/diagnostics-reexport-2.rs:10:13 + | +LL | pub mod gated { + | ^^^^^ +note: the item is gated here + --> $DIR/diagnostics-reexport-2.rs:4:5 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: could not find `gated` in `reexport2` + --> $DIR/diagnostics-reexport-2.rs:46:16 + | +LL | reexport2::gated::foo(); + | ^^^^^ could not find `gated` in `reexport2` + | +note: found an item that was configured out + --> $DIR/diagnostics-reexport-2.rs:10:13 + | +LL | pub mod gated { + | ^^^^^ +note: the item is gated here + --> $DIR/diagnostics-reexport-2.rs:4:5 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: could not find `gated` in `reexport30` + --> $DIR/diagnostics-reexport-2.rs:50:17 + | +LL | reexport30::gated::foo(); + | ^^^^^ could not find `gated` in `reexport30` + | +note: found an item that was configured out + --> $DIR/diagnostics-reexport-2.rs:10:13 + | +LL | pub mod gated { + | ^^^^^ +note: the item is gated here + --> $DIR/diagnostics-reexport-2.rs:4:5 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: could not find `gated` in `reexport31` + --> $DIR/diagnostics-reexport-2.rs:54:17 + | +LL | reexport31::gated::foo(); + | ^^^^^ could not find `gated` in `reexport31` + | +note: found an item that was configured out + --> $DIR/diagnostics-reexport-2.rs:10:13 + | +LL | pub mod gated { + | ^^^^^ +note: the item is gated here + --> $DIR/diagnostics-reexport-2.rs:4:5 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: could not find `gated` in `reexport32` + --> $DIR/diagnostics-reexport-2.rs:58:17 + | +LL | reexport32::gated::foo(); + | ^^^^^ could not find `gated` in `reexport32` + | +note: found an item that was configured out + --> $DIR/diagnostics-reexport-2.rs:10:13 + | +LL | pub mod gated { + | ^^^^^ +note: the item is gated here + --> $DIR/diagnostics-reexport-2.rs:4:5 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0433`. -- cgit 1.4.1-3-g733a5 From d562c46be0bb599ae52db2f3bd0b5c4d7645bd70 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 27 May 2025 10:05:50 -0700 Subject: CI: Add cargo tests to aarch64-apple-darwin This adds running of cargo's tests to the aarch64-apple-darwin job. The reason for this is that tier-1 targets are ostensibly supposed to run tests for host tools, but we are not doing that here. We do have fairly good coverage in Cargo's CI, but we don't have much coverage of beta or stable. I think it would be good to have a fallback here. --- src/ci/github-actions/jobs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 1d175bd97e6..fbb3729f21d 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -459,7 +459,9 @@ auto: - name: aarch64-apple env: - SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin + SCRIPT: > + ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin && + ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin src/tools/cargo RUST_CONFIGURE_ARGS: >- --enable-sanitizers --enable-profiler -- cgit 1.4.1-3-g733a5 From a55a3705f63e0a6286a21a14c4575c04b65e6853 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 28 May 2025 08:11:14 +0900 Subject: fix: Skip pattern analysis on type mismatches --- .../rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs | 3 +++ .../crates/ide-diagnostics/src/handlers/type_mismatch.rs | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 8665e9d33fc..9eb7ffe1c71 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -324,6 +324,9 @@ impl ExprValidator { let &Statement::Let { pat, initializer, else_branch: None, .. } = stmt else { continue; }; + if self.infer.type_mismatch_for_pat(pat).is_some() { + continue; + } let Some(initializer) = initializer else { continue }; let ty = &self.infer[initializer]; if ty.contains_unknown() { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 5253734867e..076df1ab0f8 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1243,4 +1243,18 @@ fn foo(v: &Enum) { "#, ); } + + #[test] + fn regression_19844() { + check_diagnostics( + r#" +fn main() { + struct S {} + enum E { V() } + let E::V() = &S {}; + // ^^^^^^ error: expected S, found E +} +"#, + ); + } } -- cgit 1.4.1-3-g733a5 From 56b669cd7adcc413bb1e64c3d2d7c347a82ae35a Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Wed, 21 May 2025 18:47:09 -0700 Subject: Disable libunwind cross-architecture unwinding Building with _LIBUNWIND_IS_NATIVE_ONLY disables code for cross-architecture unwinding it is disabled by default in LLVM [1], replicate the cmake behavior in bootstrap process It also enables some additional code that handles PAC-specific unwind info it helps compiling with the -mbranch-protection=pac or -mbranch-protection=standard flags This fixes build with clang/musl on aarch64 [1] https://github.com/llvm/llvm-project/commit/85624c5de3e831ffa01fdc2d159e3d69c30de08d Signed-off-by: Khem Raj --- src/bootstrap/src/core/build_steps/llvm.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index a3788197471..5e4a1c7d9f0 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1430,6 +1430,7 @@ impl Step for Libunwind { cfg.flag("-funwind-tables"); cfg.flag("-fvisibility=hidden"); cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None); + cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1"); cfg.include(root.join("include")); cfg.cargo_metadata(false); cfg.out_dir(&out_dir); @@ -1447,12 +1448,10 @@ impl Step for Libunwind { cfg.define("__NO_STRING_INLINES", None); cfg.define("__NO_MATH_INLINES", None); cfg.define("_LIBUNWIND_IS_BAREMETAL", None); - cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None); cfg.define("NDEBUG", None); } if self.target.is_windows() { cfg.define("_LIBUNWIND_HIDE_SYMBOLS", "1"); - cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1"); } } -- cgit 1.4.1-3-g733a5 From adcd0bf5c36ee49acf390f0d75125da4efda35ac Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 28 May 2025 09:34:08 +0800 Subject: Fix ICE in tokenstream with contracts from parser recovery --- compiler/rustc_parse/src/parser/stmt.rs | 13 ++++----- tests/crashes/140683.rs | 5 ---- ...ce-in-tokenstream-for-contracts-issue-140683.rs | 13 +++++++++ ...n-tokenstream-for-contracts-issue-140683.stderr | 34 ++++++++++++++++++++++ tests/ui/macros/no-close-delim-issue-139248.rs | 5 ++-- tests/ui/macros/no-close-delim-issue-139248.stderr | 16 ++++------ 6 files changed, 60 insertions(+), 26 deletions(-) delete mode 100644 tests/crashes/140683.rs create mode 100644 tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs create mode 100644 tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 396ded96bde..ccc3410674b 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -515,8 +515,8 @@ impl<'a> Parser<'a> { fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'a> { let prev = self.prev_token.span; let sp = self.token.span; - let mut e = self.dcx().struct_span_err(sp, msg); - self.label_expected_raw_ref(&mut e); + let mut err = self.dcx().struct_span_err(sp, msg); + self.label_expected_raw_ref(&mut err); let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon @@ -558,20 +558,19 @@ impl<'a> Parser<'a> { stmt.span }; self.suggest_fixes_misparsed_for_loop_head( - &mut e, + &mut err, prev.between(sp), stmt_span, &stmt.kind, ); } Err(e) => { - self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); - e.cancel(); + e.delay_as_bug(); } _ => {} } - e.span_label(sp, "expected `{`"); - e + err.span_label(sp, "expected `{`"); + err } fn suggest_fixes_misparsed_for_loop_head( diff --git a/tests/crashes/140683.rs b/tests/crashes/140683.rs deleted file mode 100644 index 74ea5c2533b..00000000000 --- a/tests/crashes/140683.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: #140683 -impl T { -#[core::contracts::ensures] - fn b() { (loop) } -} diff --git a/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs new file mode 100644 index 00000000000..68346a00ae1 --- /dev/null +++ b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs @@ -0,0 +1,13 @@ +#![feature(contracts)] +#![allow(incomplete_features)] + +struct T; + +impl T { + #[core::contracts::ensures] //~ ERROR expected a `Fn(&_)` closure, found `()` + fn b() {(loop)} + //~^ ERROR expected `{`, found `)` + //~| ERROR expected `{`, found `)` +} + +fn main() {} diff --git a/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr new file mode 100644 index 00000000000..f1ffda2a9be --- /dev/null +++ b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr @@ -0,0 +1,34 @@ +error: expected `{`, found `)` + --> $DIR/ice-in-tokenstream-for-contracts-issue-140683.rs:8:18 + | +LL | fn b() {(loop)} + | ----^ expected `{` + | | + | while parsing this `loop` expression + +error: expected `{`, found `)` + --> $DIR/ice-in-tokenstream-for-contracts-issue-140683.rs:8:18 + | +LL | fn b() {(loop)} + | ----^ expected `{` + | | + | while parsing this `loop` expression + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: expected a `Fn(&_)` closure, found `()` + --> $DIR/ice-in-tokenstream-for-contracts-issue-140683.rs:7:5 + | +LL | #[core::contracts::ensures] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected an `Fn(&_)` closure, found `()` + | required by a bound introduced by this call + | + = help: the trait `for<'a> Fn(&'a _)` is not implemented for `()` +note: required by a bound in `build_check_ensures` + --> $SRC_DIR/core/src/contracts.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/macros/no-close-delim-issue-139248.rs b/tests/ui/macros/no-close-delim-issue-139248.rs index 86583b2724e..f15234eaff1 100644 --- a/tests/ui/macros/no-close-delim-issue-139248.rs +++ b/tests/ui/macros/no-close-delim-issue-139248.rs @@ -2,9 +2,8 @@ macro_rules! m { (static a : () = $e:expr) => { - static a : () = $e; - //~^ ERROR macro expansion ends with an incomplete expression: expected expression - } + static a: () = $e; + }; } m! { static a : () = (if b) } diff --git a/tests/ui/macros/no-close-delim-issue-139248.stderr b/tests/ui/macros/no-close-delim-issue-139248.stderr index 6ed41ae9b46..8aa39851b4b 100644 --- a/tests/ui/macros/no-close-delim-issue-139248.stderr +++ b/tests/ui/macros/no-close-delim-issue-139248.stderr @@ -1,33 +1,27 @@ error: expected `{`, found `)` - --> $DIR/no-close-delim-issue-139248.rs:10:27 + --> $DIR/no-close-delim-issue-139248.rs:9:27 | LL | m! { static a : () = (if b) } | ^ expected `{` | note: the `if` expression is missing a block after this condition - --> $DIR/no-close-delim-issue-139248.rs:10:26 + --> $DIR/no-close-delim-issue-139248.rs:9:26 | LL | m! { static a : () = (if b) } | ^ error: expected `{`, found `)` - --> $DIR/no-close-delim-issue-139248.rs:10:27 + --> $DIR/no-close-delim-issue-139248.rs:9:27 | LL | m! { static a : () = (if b) } | ^ expected `{` | note: the `if` expression is missing a block after this condition - --> $DIR/no-close-delim-issue-139248.rs:10:26 + --> $DIR/no-close-delim-issue-139248.rs:9:26 | LL | m! { static a : () = (if b) } | ^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: macro expansion ends with an incomplete expression: expected expression - --> $DIR/no-close-delim-issue-139248.rs:5:28 - | -LL | static a : () = $e; - | ^ expected expression - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 9f94b13d7a548ccf123c5b84130a8a86cb995d5b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 28 May 2025 03:52:08 +0000 Subject: chore: Remove support for `concat_idents!` `concat_idents!` was deprecated in [1] and will be removed in the near future. rust-analyzer's support is independent of rustc's, so drop RA support now to make syncing easier. [1]: https://github.com/rust-lang/rust/pull/137653 --- .../src/macro_expansion_tests/builtin_fn_macro.rs | 18 ---------------- .../crates/hir-expand/src/builtin/fn_macro.rs | 25 ---------------------- .../crates/intern/src/symbol/symbols.rs | 1 - 3 files changed, 44 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 3027aff3163..293868df613 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 @@ -509,24 +509,6 @@ fn main() { "s"; } ); } -#[test] -fn test_concat_idents_expand() { - check( - r##" -#[rustc_builtin_macro] -macro_rules! concat_idents {} - -fn main() { concat_idents!(foo, bar); } -"##, - expect![[r##" -#[rustc_builtin_macro] -macro_rules! concat_idents {} - -fn main() { foobar; } -"##]], - ); -} - #[test] fn test_quote_string() { check( 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 539c7277284..3180b8dae10 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 @@ -140,7 +140,6 @@ register_builtin! { EagerExpander: (compile_error, CompileError) => compile_error_expand, (concat, Concat) => concat_expand, - (concat_idents, ConcatIdents) => concat_idents_expand, (concat_bytes, ConcatBytes) => concat_bytes_expand, (include, Include) => include_expand, (include_bytes, IncludeBytes) => include_bytes_expand, @@ -660,30 +659,6 @@ fn concat_bytes_expand_subtree( Ok(()) } -fn concat_idents_expand( - _db: &dyn ExpandDatabase, - _arg_id: MacroCallId, - tt: &tt::TopSubtree, - span: Span, -) -> ExpandResult { - let mut err = None; - let mut ident = String::new(); - for (i, t) in tt.iter().enumerate() { - match t { - TtElement::Leaf(tt::Leaf::Ident(id)) => { - ident.push_str(id.sym.as_str()); - } - TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), - _ => { - err.get_or_insert(ExpandError::other(span, "unexpected token")); - } - } - } - // FIXME merge spans - let ident = tt::Ident { sym: Symbol::intern(&ident), span, is_raw: tt::IdentIsRaw::No }; - ExpandResult { value: quote!(span =>#ident), err } -} - fn relative_file( db: &dyn ExpandDatabase, call_id: MacroCallId, 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 abde48d1512..fc922dd849f 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -164,7 +164,6 @@ define_symbols! { completion, compile_error, concat_bytes, - concat_idents, concat, const_format_args, const_panic_fmt, -- cgit 1.4.1-3-g733a5 From cfe488c7a0bf154dd060404b35d55a482c307817 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 06:56:48 +0200 Subject: fix: Fix IDE layer not resolving some macro calls --- .../crates/hir-def/src/nameres/assoc.rs | 4 +-- .../rust-analyzer/crates/hir/src/semantics.rs | 32 +++-------------- .../crates/hir/src/semantics/child_by_source.rs | 19 +++++++--- .../rust-analyzer/crates/ide/src/expand_macro.rs | 40 ++++++++++++++++++++++ .../crates/rust-analyzer/src/cli/analysis_stats.rs | 2 +- 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs index d45709b8b90..86225d33b4e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -75,7 +75,7 @@ impl TraitItems { }) } - pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { + pub fn macro_calls(&self) -> impl Iterator, MacroCallId)> + '_ { self.macro_calls.iter().flat_map(|it| it.iter()).copied() } } @@ -109,7 +109,7 @@ impl ImplItems { (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) } - pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { + pub fn macro_calls(&self) -> impl Iterator, MacroCallId)> + '_ { self.macro_calls.iter().flat_map(|it| it.iter()).copied() } } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 117d9c49200..5823f6260bf 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -408,11 +408,7 @@ impl<'db> SemanticsImpl<'db> { } pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option> { - let sa = self.analyze_no_infer(macro_call.syntax())?; - - let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = sa.expansion(self.db, macro_call)?; - + let file_id = self.to_def(macro_call)?; let node = self.parse_or_expand(file_id.into()); Some(InFile::new(file_id.into(), node)) } @@ -434,10 +430,7 @@ impl<'db> SemanticsImpl<'db> { &self, macro_call: &ast::MacroCall, ) -> Option> { - let sa = self.analyze_no_infer(macro_call.syntax())?; - - let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = sa.expansion(self.db, macro_call)?; + let file_id = self.to_def(macro_call)?; let macro_call = self.db.lookup_intern_macro_call(file_id); let skip = matches!( @@ -1097,16 +1090,7 @@ impl<'db> SemanticsImpl<'db> { let file_id = match m_cache.get(&mcall) { Some(&it) => it, None => { - let it = token - .parent() - .and_then(|parent| { - self.analyze_impl( - InFile::new(expansion, &parent), - None, - false, - ) - })? - .expansion(self.db, mcall.as_ref())?; + let it = ast::MacroCall::to_def(self, mcall.as_ref())?; m_cache.insert(mcall, it); it } @@ -1562,14 +1546,8 @@ impl<'db> SemanticsImpl<'db> { } pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option { - let sa = self.analyze(macro_call.syntax())?; - self.db - .parse_macro_expansion( - sa.expansion(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?, - ) - .value - .1 - .matched_arm + let file_id = self.to_def(macro_call)?; + self.db.parse_macro_expansion(file_id).value.1.matched_arm } pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index 9393d08ad3f..6accf9b2e9c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -36,9 +36,14 @@ impl ChildBySource for TraitId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let data = db.trait_items(*self); - data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( + data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { - res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db), call_id); + let ptr = ast_id.to_ptr(db); + if let Some(ptr) = ptr.cast::() { + res[keys::MACRO_CALL].insert(ptr, call_id); + } else { + res[keys::ATTR_MACRO_CALL].insert(ptr, call_id); + } }, ); data.items.iter().for_each(|&(_, item)| { @@ -50,10 +55,14 @@ impl ChildBySource for TraitId { impl ChildBySource for ImplId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let data = db.impl_items(*self); - // FIXME: Macro calls - data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( + data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { - res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db), call_id); + let ptr = ast_id.to_ptr(db); + if let Some(ptr) = ptr.cast::() { + res[keys::MACRO_CALL].insert(ptr, call_id); + } else { + res[keys::ATTR_MACRO_CALL].insert(ptr, call_id); + } }, ); data.items.iter().for_each(|&(_, item)| { diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 9beed2cac13..f8f9378b9e9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -719,4 +719,44 @@ __log!(written:%; "Test"$0); "#]], ); } + + #[test] + fn assoc_call() { + check( + r#" +macro_rules! mac { + () => { fn assoc() {} } +} +impl () { + mac$0!(); +} + "#, + expect![[r#" + mac! + fn assoc(){}"#]], + ); + } + + #[test] + fn eager() { + check( + r#" +//- minicore: concat +macro_rules! my_concat { + ($head:expr, $($tail:tt)*) => { concat!($head, $($tail)*) }; +} + + +fn test() { + _ = my_concat!( + conc$0at!("<", ">"), + "hi", + ); +} + "#, + expect![[r#" + my_concat! + "<>hi""#]], + ); + } } 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 671e838421f..12b393b80c0 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 @@ -1023,7 +1023,7 @@ impl flags::AnalysisStats { percentage(num_pats_partially_unknown, num_pats), num_pat_type_mismatches ); - eprintln!(" panics: {}", panics); + eprintln!(" panics: {panics}"); eprintln!("{:<20} {}", "Inference:", inference_time); report_metric("unknown type", num_exprs_unknown, "#"); report_metric("type mismatches", num_expr_type_mismatches, "#"); -- cgit 1.4.1-3-g733a5 From 711546a329170d741a1f422063d7082e8d8a75e5 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 07:05:48 +0200 Subject: Drop unnecessay code --- .../rust-analyzer/crates/hir/src/semantics.rs | 7 +---- .../crates/hir/src/source_analyzer.rs | 31 ++-------------------- 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 5823f6260bf..0dac64d6f2c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -567,9 +567,7 @@ impl<'db> SemanticsImpl<'db> { speculative_args: &ast::TokenTree, token_to_map: SyntaxToken, ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { - let analyzer = self.analyze_no_infer(actual_macro_call.syntax())?; - let macro_call = InFile::new(analyzer.file_id, actual_macro_call); - let macro_file = analyzer.expansion(self.db, macro_call)?; + let macro_file = self.to_def(actual_macro_call)?; hir_expand::db::expand_speculative( self.db, macro_file, @@ -1535,9 +1533,6 @@ impl<'db> SemanticsImpl<'db> { .and_then(|call| macro_call_to_macro_id(ctx, call)) .map(Into::into) }) - .or_else(|| { - self.analyze(macro_call.value.syntax())?.resolve_macro_call(self.db, macro_call) - }) } pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool { 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 be581292152..d22812d3c69 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -26,12 +26,12 @@ use hir_def::{ }, hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lang_item::LangItem, - nameres::{MacroSubNs, block_def_map, crate_def_map}, + nameres::MacroSubNs, resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope}, type_ref::{Mutability, TypeRefId}, }; use hir_expand::{ - HirFileId, InFile, MacroCallId, + HirFileId, InFile, mod_path::{ModPath, PathKind, path}, name::{AsName, Name}, }; @@ -218,18 +218,6 @@ impl<'db> SourceAnalyzer<'db> { }) } - pub(crate) fn expansion( - &self, - db: &dyn HirDatabase, - macro_call: InFile<&ast::MacroCall>, - ) -> Option { - self.store_sm().and_then(|sm| sm.expansion(macro_call)).or_else(|| { - let ast_id_map = db.ast_id_map(macro_call.file_id); - let call_ast_id = macro_call.with_value(ast_id_map.ast_id(macro_call.value)); - self.resolver.item_scopes().find_map(|scope| scope.macro_invoc(call_ast_id)) - }) - } - fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc { self.body_().map(|(def, ..)| def).map_or_else( || TraitEnvironment::empty(self.resolver.krate()), @@ -753,21 +741,6 @@ impl<'db> SourceAnalyzer<'db> { )) } - pub(crate) fn resolve_macro_call( - &self, - db: &dyn HirDatabase, - macro_call: InFile<&ast::MacroCall>, - ) -> Option { - self.expansion(db, macro_call).and_then(|it| { - let def = it.lookup(db).def; - let def_map = match def.block { - Some(block) => block_def_map(db, base_db::salsa::plumbing::FromId::from_id(block)), - None => crate_def_map(db, def.krate), - }; - def_map.macro_def_to_macro_id.get(&def.kind.erased_ast_id()).map(|it| (*it).into()) - }) - } - pub(crate) fn resolve_bind_pat_to_const( &self, db: &'db dyn HirDatabase, -- cgit 1.4.1-3-g733a5 From 7ec351ec7caa66ed4ef141f670dd4795692fd1c1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 07:06:03 +0200 Subject: Back out "Fix IDE resolution of item macros" This backs out commit 3e0ab7219a5464999652beca22698cd46e1e48e8. --- src/tools/rust-analyzer/crates/hir-def/src/db.rs | 3 --- src/tools/rust-analyzer/crates/hir-def/src/resolver.rs | 9 --------- src/tools/rust-analyzer/crates/hir-expand/src/lib.rs | 2 -- 3 files changed, 14 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 6f9340a0e4d..4a9a3b12cfa 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -422,7 +422,6 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), local_inner: false, allow_internal_unsafe: loc.allow_internal_unsafe, @@ -436,7 +435,6 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), allow_internal_unsafe: loc @@ -452,7 +450,6 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - block: None, kind: MacroDefKind::ProcMacro( InFile::new(loc.id.file_id(), makro.ast_id), loc.expander, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 416bcbb096b..16988ddf04b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -696,15 +696,6 @@ impl<'db> Resolver<'db> { &def_map[local_id].scope } - pub fn item_scopes(&self) -> impl Iterator { - self.scopes() - .filter_map(move |scope| match scope { - Scope::BlockScope(m) => Some(&m.def_map[m.module_id].scope), - _ => None, - }) - .chain(std::iter::once(&self.module_scope.def_map[self.module_scope.module_id].scope)) - } - pub fn krate(&self) -> Crate { self.module_scope.def_map.krate() } 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 19cd0298e93..d844d8f41ee 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -258,8 +258,6 @@ pub struct MacroCallLoc { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { pub krate: Crate, - // FIXME: In `hir-expand` we can't refer to `BlockId`. - pub block: Option, pub edition: Edition, pub kind: MacroDefKind, pub local_inner: bool, -- cgit 1.4.1-3-g733a5 From 636495cdec1352075b03c46198a7d6d75893192d Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 28 May 2025 11:15:33 +0900 Subject: feat: Render padding information when hovering on structs --- src/tools/rust-analyzer/crates/hir/src/lib.rs | 53 +++++++++ src/tools/rust-analyzer/crates/ide/src/hover.rs | 1 + .../rust-analyzer/crates/ide/src/hover/render.rs | 76 ++++++++++-- .../rust-analyzer/crates/ide/src/hover/tests.rs | 128 +++++++++++++++++++-- .../crates/rust-analyzer/src/config.rs | 3 + .../docs/book/src/configuration_generated.md | 7 ++ src/tools/rust-analyzer/editors/code/package.json | 27 +++++ 7 files changed, 272 insertions(+), 23 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 3a91050d15f..e8218cf8611 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -5972,6 +5972,59 @@ impl Layout { } } + pub fn tail_padding(&self, field_size: &mut impl FnMut(usize) -> Option) -> Option { + match self.0.fields { + layout::FieldsShape::Primitive => None, + layout::FieldsShape::Union(_) => None, + layout::FieldsShape::Array { stride, count } => count.checked_sub(1).and_then(|tail| { + let tail_field_size = field_size(tail as usize)?; + let offset = stride.bytes() * tail; + self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size) + }), + layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => { + let tail = memory_index.last_index()?; + let tail_field_size = field_size(tail.0.into_raw().into_u32() as usize)?; + let offset = offsets.get(tail)?.bytes(); + self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size) + } + } + } + + pub fn largest_padding( + &self, + field_size: &mut impl FnMut(usize) -> Option, + ) -> Option { + match self.0.fields { + layout::FieldsShape::Primitive => None, + layout::FieldsShape::Union(_) => None, + layout::FieldsShape::Array { stride: _, count: 0 } => None, + layout::FieldsShape::Array { stride, .. } => { + let size = field_size(0)?; + stride.bytes().checked_sub(size) + } + layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => { + let mut reverse_index = vec![None; memory_index.len()]; + for (src, (mem, offset)) in memory_index.iter().zip(offsets.iter()).enumerate() { + reverse_index[*mem as usize] = Some((src, offset.bytes())); + } + if reverse_index.iter().any(|it| it.is_none()) { + stdx::never!(); + return None; + } + reverse_index + .into_iter() + .flatten() + .chain(std::iter::once((0, self.0.size.bytes()))) + .tuple_windows() + .filter_map(|((i, start), (_, end))| { + let size = field_size(i)?; + end.checked_sub(start)?.checked_sub(size) + }) + .max() + } + } + } + pub fn enum_tag_size(&self) -> Option { let tag_size = if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants { diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 873e31b4a33..8bb1c708e25 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -58,6 +58,7 @@ pub struct MemoryLayoutHoverConfig { pub size: Option, pub offset: Option, pub alignment: Option, + pub padding: Option, pub niches: bool, } 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 ad720c8a627..c24864a18bd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -630,27 +630,57 @@ pub(super) fn definition( } }, |_| None, + |_| None, + ), + Definition::Adt(it @ Adt::Struct(strukt)) => render_memory_layout( + config.memory_layout, + || it.layout(db), + |_| None, + |layout| { + let mut field_size = + |i: usize| Some(strukt.fields(db).get(i)?.layout(db).ok()?.size()); + if strukt.repr(db).is_some_and(|it| it.inhibit_struct_field_reordering()) { + Some(("tail padding", layout.tail_padding(&mut field_size)?)) + } else { + Some(("largest padding", layout.largest_padding(&mut field_size)?)) + } + }, + |_| None, + ), + Definition::Adt(it) => render_memory_layout( + config.memory_layout, + || it.layout(db), + |_| None, + |_| None, + |_| None, ), - Definition::Adt(it) => { - render_memory_layout(config.memory_layout, || it.layout(db), |_| None, |_| None) - } Definition::Variant(it) => render_memory_layout( config.memory_layout, || it.layout(db), |_| None, + |_| None, |layout| layout.enum_tag_size(), ), - Definition::TypeAlias(it) => { - render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None) - } - Definition::Local(it) => { - render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None) - } + Definition::TypeAlias(it) => render_memory_layout( + config.memory_layout, + || it.ty(db).layout(db), + |_| None, + |_| None, + |_| None, + ), + Definition::Local(it) => render_memory_layout( + config.memory_layout, + || it.ty(db).layout(db), + |_| None, + |_| None, + |_| None, + ), Definition::SelfType(it) => render_memory_layout( config.memory_layout, || it.self_ty(db).layout(db), |_| None, |_| None, + |_| None, ), _ => None, }; @@ -1055,9 +1085,13 @@ fn closure_ty( if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) { push_new_def(hir::Trait::from(trait_).into()) } - if let Some(layout) = - render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None) - { + if let Some(layout) = render_memory_layout( + config.memory_layout, + || original.layout(sema.db), + |_| None, + |_| None, + |_| None, + ) { format_to!(markup, "\n___\n{layout}"); } format_to!(markup, "{adjusted}\n\n## Captures\n{}", captures_rendered,); @@ -1142,6 +1176,7 @@ fn render_memory_layout( config: Option, layout: impl FnOnce() -> Result, offset: impl FnOnce(&Layout) -> Option, + padding: impl FnOnce(&Layout) -> Option<(&str, u64)>, tag: impl FnOnce(&Layout) -> Option, ) -> Option { let config = config?; @@ -1199,6 +1234,23 @@ fn render_memory_layout( } } + if let Some(render) = config.padding { + if let Some((padding_name, padding)) = padding(&layout) { + format_to!(label, "{padding_name} = "); + match render { + MemoryLayoutHoverRenderKind::Decimal => format_to!(label, "{padding}"), + MemoryLayoutHoverRenderKind::Hexadecimal => format_to!(label, "{padding:#X}"), + MemoryLayoutHoverRenderKind::Both if padding >= 10 => { + format_to!(label, "{padding} ({padding:#X})") + } + MemoryLayoutHoverRenderKind::Both => { + format_to!(label, "{padding}") + } + } + format_to!(label, ", "); + } + } + if config.niches { if let Some(niches) = layout.niches() { if niches > 1024 { 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 06ca24c3ec3..a281a491525 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -12,6 +12,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { size: Some(MemoryLayoutHoverRenderKind::Both), offset: Some(MemoryLayoutHoverRenderKind::Both), alignment: Some(MemoryLayoutHoverRenderKind::Both), + padding: Some(MemoryLayoutHoverRenderKind::Both), niches: true, }), documentation: true, @@ -933,7 +934,7 @@ struct Foo$0(pub u32) where u32: Copy; --- - size = 4, align = 4, no Drop + size = 4, align = 4, largest padding = 0, no Drop "#]], ); } @@ -959,7 +960,7 @@ struct Foo$0 { field: u32 } --- - size = 4, align = 4, no Drop + size = 4, align = 4, largest padding = 0, no Drop "#]], ); check( @@ -984,7 +985,7 @@ struct Foo$0 where u32: Copy { field: u32 } --- - size = 4, align = 4, no Drop + size = 4, align = 4, largest padding = 0, no Drop "#]], ); } @@ -1013,7 +1014,7 @@ fn hover_record_struct_limit() { --- - size = 12 (0xC), align = 4, no Drop + size = 12 (0xC), align = 4, largest padding = 0, no Drop "#]], ); check_hover_fields_limit( @@ -1036,7 +1037,7 @@ fn hover_record_struct_limit() { --- - size = 4, align = 4, no Drop + size = 4, align = 4, largest padding = 0, no Drop "#]], ); check_hover_fields_limit( @@ -1062,7 +1063,7 @@ fn hover_record_struct_limit() { --- - size = 16 (0x10), align = 4, no Drop + size = 16 (0x10), align = 4, largest padding = 0, no Drop "#]], ); check_hover_fields_limit( @@ -1083,7 +1084,7 @@ fn hover_record_struct_limit() { --- - size = 12 (0xC), align = 4, no Drop + size = 12 (0xC), align = 4, largest padding = 0, no Drop "#]], ); check_hover_fields_limit( @@ -1104,7 +1105,7 @@ fn hover_record_struct_limit() { --- - size = 12 (0xC), align = 4, no Drop + size = 12 (0xC), align = 4, largest padding = 0, no Drop "#]], ); @@ -3114,7 +3115,7 @@ struct S$0(core::marker::PhantomData); --- - size = 0, align = 1, no Drop + size = 0, align = 1, largest padding = 0, no Drop "#]], ); } @@ -3147,6 +3148,111 @@ fn test_hover_layout_of_enum() { ); } +#[test] +fn test_hover_layout_padding_info() { + check( + r#"struct $0Foo { + x: bool, + y: i64, + z: u32, + }"#, + expect![[r#" + *Foo* + + ```rust + ra_test_fixture + ``` + + ```rust + struct Foo { + x: bool, + y: i64, + z: u32, + } + ``` + + --- + + size = 16 (0x10), align = 8, largest padding = 3, niches = 254, no Drop + "#]], + ); + + check( + r#"#[repr(align(32))] + struct $0Foo { + x: bool, + y: i64, + z: u32, + }"#, + expect![[r#" + *Foo* + + ```rust + ra_test_fixture + ``` + + ```rust + struct Foo { + x: bool, + y: i64, + z: u32, + } + ``` + + --- + + size = 32 (0x20), align = 32 (0x20), largest padding = 19 (0x13), niches = 254, no Drop + "#]], + ); + + check( + r#"#[repr(C)] + struct $0Foo { + x: bool, + y: i64, + z: u32, + }"#, + expect![[r#" + *Foo* + + ```rust + ra_test_fixture + ``` + + ```rust + struct Foo { + x: bool, + y: i64, + z: u32, + } + ``` + + --- + + size = 24 (0x18), align = 8, tail padding = 4, niches = 254, no Drop + "#]], + ); + + check( + r#"struct $0Foo(i16, u128, u64)"#, + expect![[r#" + *Foo* + + ```rust + ra_test_fixture + ``` + + ```rust + struct Foo(i16, u128, u64) + ``` + + --- + + size = 32 (0x20), align = 8, largest padding = 6, no Drop + "#]], + ); +} + #[test] fn test_hover_no_memory_layout() { check_hover_no_memory_layout( @@ -9198,7 +9304,7 @@ struct Pedro$0<'a> { --- - size = 16 (0x10), align = 8, niches = 1, no Drop + size = 16 (0x10), align = 8, largest padding = 0, niches = 1, no Drop "#]], ) } @@ -10559,7 +10665,7 @@ struct DropField$0 { --- - size = 4, align = 4, needs Drop + size = 4, align = 4, largest padding = 0, needs Drop "#]], ); check( 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 f7158235ca4..d1ca8c1a91a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -149,6 +149,8 @@ config_data! { 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 padding information in a memory layout hover. + hover_memoryLayout_padding: Option = None, /// How to render the size information in a memory layout hover. hover_memoryLayout_size: Option = Some(MemoryLayoutHoverRenderKindDef::Both), @@ -1635,6 +1637,7 @@ impl Config { size: self.hover_memoryLayout_size().map(mem_kind), offset: self.hover_memoryLayout_offset().map(mem_kind), alignment: self.hover_memoryLayout_alignment().map(mem_kind), + padding: self.hover_memoryLayout_padding().map(mem_kind), niches: self.hover_memoryLayout_niches().unwrap_or_default(), }), documentation: self.hover_documentation_enable().to_owned(), diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index de1d0ea4a35..0e07dadfb7c 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -763,6 +763,13 @@ Default: `"hexadecimal"` How to render the offset information in a memory layout hover. +## rust-analyzer.hover.memoryLayout.padding {#hover.memoryLayout.padding} + +Default: `null` + +How to render the padding information in a memory layout hover. + + ## rust-analyzer.hover.memoryLayout.size {#hover.memoryLayout.size} Default: `"both"` diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 88a90aad8c9..c8c36cd85c8 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -1779,6 +1779,33 @@ } } }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.memoryLayout.padding": { + "markdownDescription": "How to render the padding information in a memory layout hover.", + "default": null, + "anyOf": [ + { + "type": "null" + }, + { + "type": "string", + "enum": [ + "both", + "decimal", + "hexadecimal" + ], + "enumDescriptions": [ + "Render as 12 (0xC)", + "Render as 12", + "Render as 0xC" + ] + } + ] + } + } + }, { "title": "hover", "properties": { -- cgit 1.4.1-3-g733a5 From 4c4a40f6dfa7630a8817748a687cfdd1335a7358 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 May 2025 08:20:30 +1000 Subject: Reorder `ast::ItemKind::{Struct,Enum,Union}` fields. So they match the order of the parts in the source code, e.g.: ``` struct Foo { t: T, u: U } <-><----> <------------> / | \ ident generics variant_data ``` --- compiler/rustc_ast/src/ast.rs | 20 +++++++++----------- compiler/rustc_ast/src/visit.rs | 6 +++--- compiler/rustc_ast_lowering/src/item.rs | 6 +++--- compiler/rustc_ast_passes/src/ast_validation.rs | 6 +++--- compiler/rustc_ast_pretty/src/pprust/state/item.rs | 8 ++++---- compiler/rustc_builtin_macros/src/deriving/clone.rs | 4 ++-- .../src/deriving/cmp/partial_ord.rs | 2 +- .../src/deriving/coerce_pointee.rs | 2 +- .../rustc_builtin_macros/src/deriving/generic/mod.rs | 6 +++--- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 6 +++--- compiler/rustc_resolve/src/build_reduced_graph.rs | 4 ++-- compiler/rustc_resolve/src/def_collector.rs | 4 ++-- compiler/rustc_resolve/src/effective_visibilities.rs | 4 ++-- compiler/rustc_resolve/src/late.rs | 12 ++++++------ .../src/field_scoped_visibility_modifiers.rs | 2 +- .../clippy/clippy_lints/src/partial_pub_fields.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils/mod.rs | 8 ++++---- src/tools/rustfmt/src/items.rs | 4 ++-- src/tools/rustfmt/src/visitor.rs | 2 +- 20 files changed, 54 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index a16219361c0..2ececee8751 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3417,9 +3417,9 @@ impl Item { ItemKind::Fn(i) => Some(&i.generics), ItemKind::TyAlias(i) => Some(&i.generics), ItemKind::TraitAlias(_, generics, _) - | ItemKind::Enum(_, _, generics) - | ItemKind::Struct(_, _, generics) - | ItemKind::Union(_, _, generics) => Some(&generics), + | ItemKind::Enum(_, generics, _) + | ItemKind::Struct(_, generics, _) + | ItemKind::Union(_, generics, _) => Some(&generics), ItemKind::Trait(i) => Some(&i.generics), ItemKind::Impl(i) => Some(&i.generics), } @@ -3663,15 +3663,15 @@ pub enum ItemKind { /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. - Enum(Ident, EnumDef, Generics), + Enum(Ident, Generics, EnumDef), /// A struct definition (`struct`). /// /// E.g., `struct Foo { x: A }`. - Struct(Ident, VariantData, Generics), + Struct(Ident, Generics, VariantData), /// A union definition (`union`). /// /// E.g., `union Foo { x: A, y: B }`. - Union(Ident, VariantData, Generics), + Union(Ident, Generics, VariantData), /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. @@ -3688,10 +3688,8 @@ pub enum ItemKind { /// /// E.g., `foo!(..)`. MacCall(P), - /// A macro definition. MacroDef(Ident, MacroDef), - /// A single delegation item (`reuse`). /// /// E.g. `reuse ::name { target_expr_template }`. @@ -3767,9 +3765,9 @@ impl ItemKind { Self::Fn(box Fn { generics, .. }) | Self::TyAlias(box TyAlias { generics, .. }) | Self::Const(box ConstItem { generics, .. }) - | Self::Enum(_, _, generics) - | Self::Struct(_, _, generics) - | Self::Union(_, _, generics) + | Self::Enum(_, generics, _) + | Self::Struct(_, generics, _) + | Self::Union(_, generics, _) | Self::Trait(box Trait { generics, .. }) | Self::TraitAlias(_, generics, _) | Self::Impl(box Impl { generics, .. }) => Some(generics), diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index bf5c402e52e..1cc11b58dd9 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -508,7 +508,7 @@ macro_rules! common_visitor_and_walkers { )? $(>::Result::output())? } - ItemKind::Enum(ident, enum_definition, generics) => { + ItemKind::Enum(ident, generics, enum_definition) => { try_visit!(vis.visit_ident(ident)); try_visit!(vis.visit_generics(generics)); $(${ignore($mut)} @@ -516,8 +516,8 @@ macro_rules! common_visitor_and_walkers { )? $(${ignore($lt)}vis.visit_enum_def(enum_definition))? } - ItemKind::Struct(ident, variant_data, generics) - | ItemKind::Union(ident, variant_data, generics) => { + ItemKind::Struct(ident, generics, variant_data) + | ItemKind::Union(ident, generics, variant_data) => { try_visit!(vis.visit_ident(ident)); try_visit!(vis.visit_generics(generics)); vis.visit_variant_data(variant_data) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e98d6c50ee7..7f7d45790ee 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -306,7 +306,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TyAlias(ident, ty, generics) } - ItemKind::Enum(ident, enum_definition, generics) => { + ItemKind::Enum(ident, generics, enum_definition) => { let ident = self.lower_ident(*ident); let (generics, variants) = self.lower_generics( generics, @@ -320,7 +320,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics) } - ItemKind::Struct(ident, struct_def, generics) => { + ItemKind::Struct(ident, generics, struct_def) => { let ident = self.lower_ident(*ident); let (generics, struct_def) = self.lower_generics( generics, @@ -330,7 +330,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Struct(ident, struct_def, generics) } - ItemKind::Union(ident, vdata, generics) => { + ItemKind::Union(ident, generics, vdata) => { let ident = self.lower_ident(*ident); let (generics, vdata) = self.lower_generics( generics, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index cbf4f2f5eb2..d6fe04d2994 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1010,7 +1010,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); self.extern_mod_span = old_item; } - ItemKind::Enum(_, def, _) => { + ItemKind::Enum(_, _, def) => { for variant in &def.variants { self.visibility_not_permitted( &variant.vis, @@ -1061,7 +1061,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } visit::walk_item(self, item) } - ItemKind::Struct(ident, vdata, generics) => match vdata { + ItemKind::Struct(ident, generics, vdata) => match vdata { VariantData::Struct { fields, .. } => { self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); self.visit_generics(generics); @@ -1070,7 +1070,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } _ => visit::walk_item(self, item), }, - ItemKind::Union(ident, vdata, generics) => { + ItemKind::Union(ident, generics, vdata) => { if vdata.fields().is_empty() { self.dcx().emit_err(errors::FieldlessUnion { span: item.span }); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 70cf2f2a459..3638eb31c61 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -298,14 +298,14 @@ impl<'a> State<'a> { *defaultness, ); } - ast::ItemKind::Enum(ident, enum_definition, params) => { - self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis); + ast::ItemKind::Enum(ident, generics, enum_definition) => { + self.print_enum_def(enum_definition, generics, *ident, item.span, &item.vis); } - ast::ItemKind::Struct(ident, struct_def, generics) => { + ast::ItemKind::Struct(ident, generics, struct_def) => { let (cb, ib) = self.head(visibility_qualified(&item.vis, "struct")); self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib); } - ast::ItemKind::Union(ident, struct_def, generics) => { + ast::ItemKind::Union(ident, generics, struct_def) => { let (cb, ib) = self.head(visibility_qualified(&item.vis, "union")); self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib); } diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 44cf215c662..69f8c273797 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone( let is_simple; match item { Annotatable::Item(annitem) => match &annitem.kind { - ItemKind::Struct(_, _, Generics { params, .. }) - | ItemKind::Enum(_, _, Generics { params, .. }) => { + ItemKind::Struct(_, Generics { params, .. }, _) + | ItemKind::Enum(_, Generics { params, .. }, _) => { let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let has_derive_copy = cx.resolver.has_derive_copy(container_id); if has_derive_copy diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index aa01da3151e..0a076dd670b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord( // Order in which to perform matching let discr_then_data = if let Annotatable::Item(item) = item - && let ItemKind::Enum(_, def, _) = &item.kind + && let ItemKind::Enum(_, _, def) = &item.kind { let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); match dataful.iter().filter(|&&b| b).count() { diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 446d8afeedd..0794192621a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee( item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); let (name_ident, generics) = if let Annotatable::Item(aitem) = item - && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind + && let ItemKind::Struct(ident, g, struct_data) = &aitem.kind { if !matches!( struct_data, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 9aa53f9e4f7..f1bef526c10 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -488,7 +488,7 @@ impl<'a> TraitDef<'a> { ); let newitem = match &item.kind { - ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def( + ast::ItemKind::Struct(ident, generics, struct_def) => self.expand_struct_def( cx, struct_def, *ident, @@ -496,7 +496,7 @@ impl<'a> TraitDef<'a> { from_scratch, is_packed, ), - ast::ItemKind::Enum(ident, enum_def, generics) => { + ast::ItemKind::Enum(ident, generics, enum_def) => { // We ignore `is_packed` here, because `repr(packed)` // enums cause an error later on. // @@ -504,7 +504,7 @@ impl<'a> TraitDef<'a> { // downstream in blatantly illegal code, so it is fine. self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) } - ast::ItemKind::Union(ident, struct_def, generics) => { + ast::ItemKind::Union(ident, generics, struct_def) => { if self.supports_unions { self.expand_struct_def( cx, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 55751aa4908..2accfba383e 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1424,7 +1424,7 @@ pub fn parse_macro_name_and_helper_attrs( /// See #73345 and #83125 for more details. /// FIXME(#73933): Remove this eventually. fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) { - if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind + if let ast::ItemKind::Enum(ident, _, enum_def) = &item.kind && ident.name == sym::ProceduralMasqueradeDummyType && let [variant] = &*enum_def.variants && variant.ident.name == sym::Input diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index babc55ccc0f..c7b0eb11e5a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1577,7 +1577,7 @@ impl<'a> Parser<'a> { }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; - Ok(ItemKind::Enum(ident, enum_definition, generics)) + Ok(ItemKind::Enum(ident, generics, enum_definition)) } fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option> { @@ -1732,7 +1732,7 @@ impl<'a> Parser<'a> { return Err(self.dcx().create_err(err)); }; - Ok(ItemKind::Struct(ident, vdata, generics)) + Ok(ItemKind::Struct(ident, generics, vdata)) } /// Parses `union Foo { ... }`. @@ -1764,7 +1764,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok(ItemKind::Union(ident, vdata, generics)) + Ok(ItemKind::Union(ident, generics, vdata)) } /// This function parses the fields of record structs: diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3460c53782f..c30ed781f35 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -823,7 +823,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in both the type and value namespaces. - ItemKind::Struct(ident, ref vdata, _) => { + ItemKind::Struct(ident, _, ref vdata) => { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, @@ -874,7 +874,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } } - ItemKind::Union(ident, ref vdata, _) => { + ItemKind::Union(ident, _, ref vdata) => { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 13dfb59f27f..25485be5622 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -162,8 +162,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { self.with_parent(def_id, |this| { this.with_impl_trait(ImplTraitContext::Existential, |this| { match i.kind { - ItemKind::Struct(_, ref struct_def, _) - | ItemKind::Union(_, ref struct_def, _) => { + ItemKind::Struct(_, _, ref struct_def) + | ItemKind::Union(_, _, ref struct_def) => { // If this is a unit or tuple-like struct, register the constructor. if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) { this.create_def( diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index a5ca4565d7b..5de80de3f8d 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -252,7 +252,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> self.current_private_vis = prev_private_vis; } - ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => { + ast::ItemKind::Enum(_, _, EnumDef { ref variants }) => { self.set_bindings_effective_visibilities(def_id); for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); @@ -262,7 +262,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> } } - ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => { + ast::ItemKind::Struct(_, _, ref def) | ast::ItemKind::Union(_, _, ref def) => { for field in def.fields() { self.update_field(self.r.local_def_id(field.id), def_id); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fd977a8eb6c..4cfa079e49b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2694,9 +2694,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - ItemKind::Enum(_, _, ref generics) - | ItemKind::Struct(_, _, ref generics) - | ItemKind::Union(_, _, ref generics) => { + ItemKind::Enum(_, ref generics, _) + | ItemKind::Struct(_, ref generics, _) + | ItemKind::Union(_, ref generics, _) => { self.resolve_adt(item, generics); } @@ -5243,9 +5243,9 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { ItemKind::TyAlias(box TyAlias { generics, .. }) | ItemKind::Const(box ConstItem { generics, .. }) | ItemKind::Fn(box Fn { generics, .. }) - | ItemKind::Enum(_, _, generics) - | ItemKind::Struct(_, _, generics) - | ItemKind::Union(_, _, generics) + | ItemKind::Enum(_, generics, _) + | ItemKind::Struct(_, generics, _) + | ItemKind::Union(_, generics, _) | ItemKind::Impl(box Impl { generics, .. }) | ItemKind::Trait(box Trait { generics, .. }) | ItemKind::TraitAlias(_, generics, _) => { diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs index aae8291905d..dfb0b4f103c 100644 --- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs +++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs @@ -51,7 +51,7 @@ declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MO impl EarlyLintPass for FieldScopedVisibilityModifiers { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let ItemKind::Struct(_, ref st, _) = item.kind else { + let ItemKind::Struct(_, _, ref st) = item.kind else { return; }; for field in st.fields() { diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs index cda752d003f..65e93af9420 100644 --- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs +++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs @@ -41,7 +41,7 @@ declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]); impl EarlyLintPass for PartialPubFields { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let ItemKind::Struct(_, ref st, _) = item.kind else { + let ItemKind::Struct(_, _, ref st) = item.kind else { return; }; diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 8996b694ed8..a0503a699e6 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -436,11 +436,11 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && over(lb, rb, eq_generic_bound) && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r)) }, - (Enum(li, le, lg), Enum(ri, re, rg)) => { - eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg) + (Enum(li, lg, le), Enum(ri, rg, re)) => { + eq_id(*li, *ri) && eq_generics(lg, rg) && over(&le.variants, &re.variants, eq_variant) }, - (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => { - eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg) + (Struct(li, lg, lv), Struct(ri, rg, rv)) | (Union(li, lg, lv), Union(ri, rg, rv)) => { + eq_id(*li, *ri) && eq_generics(lg, rg) && eq_variant_data(lv, rv) }, ( Trait(box ast::Trait { diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index e79b7803c60..1a3897b51cb 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1110,10 +1110,10 @@ impl<'a> StructParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (prefix, def, ident, generics) = match item.kind { - ast::ItemKind::Struct(ident, ref def, ref generics) => { + ast::ItemKind::Struct(ident, ref generics, ref def) => { ("struct ", def, ident, generics) } - ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics), + ast::ItemKind::Union(ident, ref generics, ref def) => ("union ", def, ident, generics), _ => unreachable!(), }; StructParts { diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 16d1f5105d5..f6a9a3f2cd1 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -521,7 +521,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { self.visit_struct(&StructParts::from_item(item)); } - ast::ItemKind::Enum(ident, ref def, ref generics) => { + ast::ItemKind::Enum(ident, ref generics, ref def) => { self.format_missing_with_indent(source!(self, item.span).lo()); self.visit_enum(ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); -- cgit 1.4.1-3-g733a5 From 2a9363e59389dcfcb28146d4c8f4e4ce179ded77 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 May 2025 08:37:45 +0200 Subject: coretests: simplify test_float macro to derive more things from the type name --- library/coretests/tests/num/mod.rs | 236 ++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 134 deletions(-) diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index a6b75f70266..cdde5b883aa 100644 --- a/library/coretests/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs @@ -732,7 +732,7 @@ assume_usize_width! { } macro_rules! test_float { - ($modname: ident, $fassert: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => { + ($modname: ident, $fassert: ident, $fty: ty) => { mod $modname { #[test] fn min() { @@ -747,19 +747,19 @@ macro_rules! test_float { $fassert!((-0.0 as $fty).min(9.0), -0.0); $fassert!((-0.0 as $fty).min(9.0).is_sign_negative()); $fassert!((-0.0 as $fty).min(-9.0), -9.0); - $fassert!(($inf as $fty).min(9.0), 9.0); - $fassert!((9.0 as $fty).min($inf), 9.0); - $fassert!(($inf as $fty).min(-9.0), -9.0); - $fassert!((-9.0 as $fty).min($inf), -9.0); - $fassert!(($neginf as $fty).min(9.0), $neginf); - $fassert!((9.0 as $fty).min($neginf), $neginf); - $fassert!(($neginf as $fty).min(-9.0), $neginf); - $fassert!((-9.0 as $fty).min($neginf), $neginf); - $fassert!(($nan as $fty).min(9.0), 9.0); - $fassert!(($nan as $fty).min(-9.0), -9.0); - $fassert!((9.0 as $fty).min($nan), 9.0); - $fassert!((-9.0 as $fty).min($nan), -9.0); - $fassert!(($nan as $fty).min($nan).is_nan()); + $fassert!((<$fty>::INFINITY as $fty).min(9.0), 9.0); + $fassert!((9.0 as $fty).min(<$fty>::INFINITY), 9.0); + $fassert!((<$fty>::INFINITY as $fty).min(-9.0), -9.0); + $fassert!((-9.0 as $fty).min(<$fty>::INFINITY), -9.0); + $fassert!((<$fty>::NEG_INFINITY as $fty).min(9.0), <$fty>::NEG_INFINITY); + $fassert!((9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); + $fassert!((<$fty>::NEG_INFINITY as $fty).min(-9.0), <$fty>::NEG_INFINITY); + $fassert!((-9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); + $fassert!((<$fty>::NAN as $fty).min(9.0), 9.0); + $fassert!((<$fty>::NAN as $fty).min(-9.0), -9.0); + $fassert!((9.0 as $fty).min(<$fty>::NAN), 9.0); + $fassert!((-9.0 as $fty).min(<$fty>::NAN), -9.0); + $fassert!((<$fty>::NAN as $fty).min(<$fty>::NAN).is_nan()); } #[test] fn max() { @@ -777,19 +777,19 @@ macro_rules! test_float { $fassert!((0.0 as $fty).max(-9.0).is_sign_positive()); $fassert!((-0.0 as $fty).max(-9.0), -0.0); $fassert!((-0.0 as $fty).max(-9.0).is_sign_negative()); - $fassert!(($inf as $fty).max(9.0), $inf); - $fassert!((9.0 as $fty).max($inf), $inf); - $fassert!(($inf as $fty).max(-9.0), $inf); - $fassert!((-9.0 as $fty).max($inf), $inf); - $fassert!(($neginf as $fty).max(9.0), 9.0); - $fassert!((9.0 as $fty).max($neginf), 9.0); - $fassert!(($neginf as $fty).max(-9.0), -9.0); - $fassert!((-9.0 as $fty).max($neginf), -9.0); - $fassert!(($nan as $fty).max(9.0), 9.0); - $fassert!(($nan as $fty).max(-9.0), -9.0); - $fassert!((9.0 as $fty).max($nan), 9.0); - $fassert!((-9.0 as $fty).max($nan), -9.0); - $fassert!(($nan as $fty).max($nan).is_nan()); + $fassert!((<$fty>::INFINITY as $fty).max(9.0), <$fty>::INFINITY); + $fassert!((9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY); + $fassert!((<$fty>::INFINITY as $fty).max(-9.0), <$fty>::INFINITY); + $fassert!((-9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY); + $fassert!((<$fty>::NEG_INFINITY as $fty).max(9.0), 9.0); + $fassert!((9.0 as $fty).max(<$fty>::NEG_INFINITY), 9.0); + $fassert!((<$fty>::NEG_INFINITY as $fty).max(-9.0), -9.0); + $fassert!((-9.0 as $fty).max(<$fty>::NEG_INFINITY), -9.0); + $fassert!((<$fty>::NAN as $fty).max(9.0), 9.0); + $fassert!((<$fty>::NAN as $fty).max(-9.0), -9.0); + $fassert!((9.0 as $fty).max(<$fty>::NAN), 9.0); + $fassert!((-9.0 as $fty).max(<$fty>::NAN), -9.0); + $fassert!((<$fty>::NAN as $fty).max(<$fty>::NAN).is_nan()); } #[test] fn minimum() { @@ -806,19 +806,19 @@ macro_rules! test_float { $fassert!((-0.0 as $fty).minimum(9.0), -0.0); $fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative()); $fassert!((-0.0 as $fty).minimum(-9.0), -9.0); - $fassert!(($inf as $fty).minimum(9.0), 9.0); - $fassert!((9.0 as $fty).minimum($inf), 9.0); - $fassert!(($inf as $fty).minimum(-9.0), -9.0); - $fassert!((-9.0 as $fty).minimum($inf), -9.0); - $fassert!(($neginf as $fty).minimum(9.0), $neginf); - $fassert!((9.0 as $fty).minimum($neginf), $neginf); - $fassert!(($neginf as $fty).minimum(-9.0), $neginf); - $fassert!((-9.0 as $fty).minimum($neginf), $neginf); - $fassert!(($nan as $fty).minimum(9.0).is_nan()); - $fassert!(($nan as $fty).minimum(-9.0).is_nan()); - $fassert!((9.0 as $fty).minimum($nan).is_nan()); - $fassert!((-9.0 as $fty).minimum($nan).is_nan()); - $fassert!(($nan as $fty).minimum($nan).is_nan()); + $fassert!((<$fty>::INFINITY as $fty).minimum(9.0), 9.0); + $fassert!((9.0 as $fty).minimum(<$fty>::INFINITY), 9.0); + $fassert!((<$fty>::INFINITY as $fty).minimum(-9.0), -9.0); + $fassert!((-9.0 as $fty).minimum(<$fty>::INFINITY), -9.0); + $fassert!((<$fty>::NEG_INFINITY as $fty).minimum(9.0), <$fty>::NEG_INFINITY); + $fassert!((9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); + $fassert!((<$fty>::NEG_INFINITY as $fty).minimum(-9.0), <$fty>::NEG_INFINITY); + $fassert!((-9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); + $fassert!((<$fty>::NAN as $fty).minimum(9.0).is_nan()); + $fassert!((<$fty>::NAN as $fty).minimum(-9.0).is_nan()); + $fassert!((9.0 as $fty).minimum(<$fty>::NAN).is_nan()); + $fassert!((-9.0 as $fty).minimum(<$fty>::NAN).is_nan()); + $fassert!((<$fty>::NAN as $fty).minimum(<$fty>::NAN).is_nan()); } #[test] fn maximum() { @@ -838,19 +838,19 @@ macro_rules! test_float { $fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive()); $fassert!((-0.0 as $fty).maximum(-9.0), -0.0); $fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative()); - $fassert!(($inf as $fty).maximum(9.0), $inf); - $fassert!((9.0 as $fty).maximum($inf), $inf); - $fassert!(($inf as $fty).maximum(-9.0), $inf); - $fassert!((-9.0 as $fty).maximum($inf), $inf); - $fassert!(($neginf as $fty).maximum(9.0), 9.0); - $fassert!((9.0 as $fty).maximum($neginf), 9.0); - $fassert!(($neginf as $fty).maximum(-9.0), -9.0); - $fassert!((-9.0 as $fty).maximum($neginf), -9.0); - $fassert!(($nan as $fty).maximum(9.0).is_nan()); - $fassert!(($nan as $fty).maximum(-9.0).is_nan()); - $fassert!((9.0 as $fty).maximum($nan).is_nan()); - $fassert!((-9.0 as $fty).maximum($nan).is_nan()); - $fassert!(($nan as $fty).maximum($nan).is_nan()); + $fassert!((<$fty>::INFINITY as $fty).maximum(9.0), <$fty>::INFINITY); + $fassert!((9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY); + $fassert!((<$fty>::INFINITY as $fty).maximum(-9.0), <$fty>::INFINITY); + $fassert!((-9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY); + $fassert!((<$fty>::NEG_INFINITY as $fty).maximum(9.0), 9.0); + $fassert!((9.0 as $fty).maximum(<$fty>::NEG_INFINITY), 9.0); + $fassert!((<$fty>::NEG_INFINITY as $fty).maximum(-9.0), -9.0); + $fassert!((-9.0 as $fty).maximum(<$fty>::NEG_INFINITY), -9.0); + $fassert!((<$fty>::NAN as $fty).maximum(9.0).is_nan()); + $fassert!((<$fty>::NAN as $fty).maximum(-9.0).is_nan()); + $fassert!((9.0 as $fty).maximum(<$fty>::NAN).is_nan()); + $fassert!((-9.0 as $fty).maximum(<$fty>::NAN).is_nan()); + $fassert!((<$fty>::NAN as $fty).maximum(<$fty>::NAN).is_nan()); } #[test] fn midpoint() { @@ -863,38 +863,50 @@ macro_rules! test_float { $fassert!((0.0 as $fty).midpoint(0.0), 0.0); $fassert!((-0.0 as $fty).midpoint(-0.0), -0.0); $fassert!((-5.0 as $fty).midpoint(5.0), 0.0); - $fassert!(($max as $fty).midpoint($min), 0.0); - $fassert!(($min as $fty).midpoint($max), -0.0); - $fassert!(($max as $fty).midpoint($min_pos), $max / 2.); - $fassert!((-$max as $fty).midpoint($min_pos), -$max / 2.); - $fassert!(($max as $fty).midpoint(-$min_pos), $max / 2.); - $fassert!((-$max as $fty).midpoint(-$min_pos), -$max / 2.); - $fassert!(($min_pos as $fty).midpoint($max), $max / 2.); - $fassert!(($min_pos as $fty).midpoint(-$max), -$max / 2.); - $fassert!((-$min_pos as $fty).midpoint($max), $max / 2.); - $fassert!((-$min_pos as $fty).midpoint(-$max), -$max / 2.); - $fassert!(($max as $fty).midpoint($max), $max); - $fassert!(($min_pos as $fty).midpoint($min_pos), $min_pos); - $fassert!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos); - $fassert!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5); - $fassert!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5); - $fassert!(($inf as $fty).midpoint($inf), $inf); - $fassert!(($neginf as $fty).midpoint($neginf), $neginf); - $fassert!(($nan as $fty).midpoint(1.0).is_nan()); - $fassert!((1.0 as $fty).midpoint($nan).is_nan()); - $fassert!(($nan as $fty).midpoint($nan).is_nan()); + $fassert!((<$fty>::MAX as $fty).midpoint(<$fty>::MIN), 0.0); + $fassert!((<$fty>::MIN as $fty).midpoint(<$fty>::MAX), -0.0); + $fassert!((<$fty>::MAX as $fty).midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.); + $fassert!((-<$fty>::MAX as $fty).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.); + $fassert!((<$fty>::MAX as $fty).midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.); + $fassert!( + (-<$fty>::MAX as $fty).midpoint(-<$fty>::MIN_POSITIVE), + -<$fty>::MAX / 2. + ); + $fassert!((<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.); + $fassert!((<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.); + $fassert!((-<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.); + $fassert!((-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.); + $fassert!((<$fty>::MAX as $fty).midpoint(<$fty>::MAX), <$fty>::MAX); + $fassert!( + (<$fty>::MIN_POSITIVE).midpoint(<$fty>::MIN_POSITIVE), + <$fty>::MIN_POSITIVE + ); + $fassert!( + (-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MIN_POSITIVE), + -<$fty>::MIN_POSITIVE + ); + $fassert!((<$fty>::MAX as $fty).midpoint(5.0), <$fty>::MAX / 2.0 + 2.5); + $fassert!((<$fty>::MAX as $fty).midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5); + $fassert!((<$fty>::INFINITY as $fty).midpoint(<$fty>::INFINITY), <$fty>::INFINITY); + $fassert!( + (<$fty>::NEG_INFINITY as $fty).midpoint(<$fty>::NEG_INFINITY), + <$fty>::NEG_INFINITY + ); + $fassert!((<$fty>::NAN as $fty).midpoint(1.0).is_nan()); + $fassert!((1.0 as $fty).midpoint(<$fty>::NAN).is_nan()); + $fassert!((<$fty>::NAN as $fty).midpoint(<$fty>::NAN).is_nan()); // test if large differences in magnitude are still correctly computed. // NOTE: that because of how small x and y are, x + y can never overflow // so (x + y) / 2.0 is always correct // in particular, `2.pow(i)` will never be at the max exponent, so it could // be safely doubled, while j is significantly smaller. - for i in $max_exp.saturating_sub(64)..$max_exp { + for i in <$fty>::MAX_EXP.saturating_sub(64)..<$fty>::MAX_EXP { for j in 0..64u8 { let large = <$fty>::from(2.0f32).powi(i); // a much smaller number, such that there is no chance of overflow to test // potential double rounding in midpoint's implementation. - let small = <$fty>::from(2.0f32).powi($max_exp - 1) + let small = (2.0 as $fty).powi(<$fty>::MAX_EXP - 1) * <$fty>::EPSILON * <$fty>::from(j); @@ -908,21 +920,21 @@ macro_rules! test_float { #[test] fn rem_euclid() { // FIXME: Use $fassert when rem_euclid becomes const - assert!($inf.rem_euclid((42.0 as $fty)).is_nan()); - assert_eq!((42.0 as $fty).rem_euclid($inf), (42.0 as $fty)); - assert!((42.0 as $fty).rem_euclid($nan).is_nan()); - assert!($inf.rem_euclid($inf).is_nan()); - assert!($inf.rem_euclid($nan).is_nan()); - assert!($nan.rem_euclid($inf).is_nan()); + assert!(<$fty>::INFINITY.rem_euclid((42.0 as $fty)).is_nan()); + assert_eq!((42.0 as $fty).rem_euclid(<$fty>::INFINITY), (42.0 as $fty)); + assert!((42.0 as $fty).rem_euclid(<$fty>::NAN).is_nan()); + assert!(<$fty>::INFINITY.rem_euclid(<$fty>::INFINITY).is_nan()); + assert!(<$fty>::INFINITY.rem_euclid(<$fty>::NAN).is_nan()); + assert!(<$fty>::NAN.rem_euclid(<$fty>::INFINITY).is_nan()); } #[test] fn div_euclid() { // FIXME: Use $fassert when div_euclid becomes const - assert_eq!((42.0 as $fty).div_euclid($inf), 0.0); - assert!((42.0 as $fty).div_euclid($nan).is_nan()); - assert!($inf.div_euclid($inf).is_nan()); - assert!($inf.div_euclid($nan).is_nan()); - assert!($nan.div_euclid($inf).is_nan()); + assert_eq!((42.0 as $fty).div_euclid(<$fty>::INFINITY), 0.0); + assert!((42.0 as $fty).div_euclid(<$fty>::NAN).is_nan()); + assert!(<$fty>::INFINITY.div_euclid(<$fty>::INFINITY).is_nan()); + assert!(<$fty>::INFINITY.div_euclid(<$fty>::NAN).is_nan()); + assert!(<$fty>::NAN.div_euclid(<$fty>::INFINITY).is_nan()); } } }; @@ -948,51 +960,7 @@ macro_rules! float_const_assert { }; } -test_float!( - f32, - float_assert, - f32, - f32::INFINITY, - f32::NEG_INFINITY, - f32::NAN, - f32::MIN, - f32::MAX, - f32::MIN_POSITIVE, - f32::MAX_EXP -); -test_float!( - f32_const, - float_const_assert, - f32, - f32::INFINITY, - f32::NEG_INFINITY, - f32::NAN, - f32::MIN, - f32::MAX, - f32::MIN_POSITIVE, - f32::MAX_EXP -); -test_float!( - f64, - float_assert, - f64, - f64::INFINITY, - f64::NEG_INFINITY, - f64::NAN, - f64::MIN, - f64::MAX, - f64::MIN_POSITIVE, - f64::MAX_EXP -); -test_float!( - f64_const, - float_const_assert, - f64, - f64::INFINITY, - f64::NEG_INFINITY, - f64::NAN, - f64::MIN, - f64::MAX, - f64::MIN_POSITIVE, - f64::MAX_EXP -); +test_float!(f32, float_assert, f32); +test_float!(f32_const, float_const_assert, f32); +test_float!(f64, float_assert, f64); +test_float!(f64_const, float_const_assert, f64); -- cgit 1.4.1-3-g733a5 From e0ff77aea5c723934296b8a54d485dd11fbc4d6d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 May 2025 08:42:36 +0200 Subject: coretests: add abs() and copysign() tests, and remove now-unnecessary ui test --- library/coretests/tests/num/mod.rs | 101 +++++++++++++++------------- tests/ui/consts/const-eval/float_methods.rs | 46 ------------- 2 files changed, 56 insertions(+), 91 deletions(-) delete mode 100644 tests/ui/consts/const-eval/float_methods.rs diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index cdde5b883aa..1212d36a1b1 100644 --- a/library/coretests/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs @@ -747,19 +747,19 @@ macro_rules! test_float { $fassert!((-0.0 as $fty).min(9.0), -0.0); $fassert!((-0.0 as $fty).min(9.0).is_sign_negative()); $fassert!((-0.0 as $fty).min(-9.0), -9.0); - $fassert!((<$fty>::INFINITY as $fty).min(9.0), 9.0); + $fassert!(<$fty>::INFINITY.min(9.0), 9.0); $fassert!((9.0 as $fty).min(<$fty>::INFINITY), 9.0); - $fassert!((<$fty>::INFINITY as $fty).min(-9.0), -9.0); + $fassert!(<$fty>::INFINITY.min(-9.0), -9.0); $fassert!((-9.0 as $fty).min(<$fty>::INFINITY), -9.0); - $fassert!((<$fty>::NEG_INFINITY as $fty).min(9.0), <$fty>::NEG_INFINITY); + $fassert!(<$fty>::NEG_INFINITY.min(9.0), <$fty>::NEG_INFINITY); $fassert!((9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); - $fassert!((<$fty>::NEG_INFINITY as $fty).min(-9.0), <$fty>::NEG_INFINITY); + $fassert!(<$fty>::NEG_INFINITY.min(-9.0), <$fty>::NEG_INFINITY); $fassert!((-9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); - $fassert!((<$fty>::NAN as $fty).min(9.0), 9.0); - $fassert!((<$fty>::NAN as $fty).min(-9.0), -9.0); + $fassert!(<$fty>::NAN.min(9.0), 9.0); + $fassert!(<$fty>::NAN.min(-9.0), -9.0); $fassert!((9.0 as $fty).min(<$fty>::NAN), 9.0); $fassert!((-9.0 as $fty).min(<$fty>::NAN), -9.0); - $fassert!((<$fty>::NAN as $fty).min(<$fty>::NAN).is_nan()); + $fassert!(<$fty>::NAN.min(<$fty>::NAN).is_nan()); } #[test] fn max() { @@ -777,19 +777,19 @@ macro_rules! test_float { $fassert!((0.0 as $fty).max(-9.0).is_sign_positive()); $fassert!((-0.0 as $fty).max(-9.0), -0.0); $fassert!((-0.0 as $fty).max(-9.0).is_sign_negative()); - $fassert!((<$fty>::INFINITY as $fty).max(9.0), <$fty>::INFINITY); + $fassert!(<$fty>::INFINITY.max(9.0), <$fty>::INFINITY); $fassert!((9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY); - $fassert!((<$fty>::INFINITY as $fty).max(-9.0), <$fty>::INFINITY); + $fassert!(<$fty>::INFINITY.max(-9.0), <$fty>::INFINITY); $fassert!((-9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY); - $fassert!((<$fty>::NEG_INFINITY as $fty).max(9.0), 9.0); + $fassert!(<$fty>::NEG_INFINITY.max(9.0), 9.0); $fassert!((9.0 as $fty).max(<$fty>::NEG_INFINITY), 9.0); - $fassert!((<$fty>::NEG_INFINITY as $fty).max(-9.0), -9.0); + $fassert!(<$fty>::NEG_INFINITY.max(-9.0), -9.0); $fassert!((-9.0 as $fty).max(<$fty>::NEG_INFINITY), -9.0); - $fassert!((<$fty>::NAN as $fty).max(9.0), 9.0); - $fassert!((<$fty>::NAN as $fty).max(-9.0), -9.0); + $fassert!(<$fty>::NAN.max(9.0), 9.0); + $fassert!(<$fty>::NAN.max(-9.0), -9.0); $fassert!((9.0 as $fty).max(<$fty>::NAN), 9.0); $fassert!((-9.0 as $fty).max(<$fty>::NAN), -9.0); - $fassert!((<$fty>::NAN as $fty).max(<$fty>::NAN).is_nan()); + $fassert!(<$fty>::NAN.max(<$fty>::NAN).is_nan()); } #[test] fn minimum() { @@ -806,19 +806,19 @@ macro_rules! test_float { $fassert!((-0.0 as $fty).minimum(9.0), -0.0); $fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative()); $fassert!((-0.0 as $fty).minimum(-9.0), -9.0); - $fassert!((<$fty>::INFINITY as $fty).minimum(9.0), 9.0); + $fassert!(<$fty>::INFINITY.minimum(9.0), 9.0); $fassert!((9.0 as $fty).minimum(<$fty>::INFINITY), 9.0); - $fassert!((<$fty>::INFINITY as $fty).minimum(-9.0), -9.0); + $fassert!(<$fty>::INFINITY.minimum(-9.0), -9.0); $fassert!((-9.0 as $fty).minimum(<$fty>::INFINITY), -9.0); - $fassert!((<$fty>::NEG_INFINITY as $fty).minimum(9.0), <$fty>::NEG_INFINITY); + $fassert!(<$fty>::NEG_INFINITY.minimum(9.0), <$fty>::NEG_INFINITY); $fassert!((9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); - $fassert!((<$fty>::NEG_INFINITY as $fty).minimum(-9.0), <$fty>::NEG_INFINITY); + $fassert!(<$fty>::NEG_INFINITY.minimum(-9.0), <$fty>::NEG_INFINITY); $fassert!((-9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY); - $fassert!((<$fty>::NAN as $fty).minimum(9.0).is_nan()); - $fassert!((<$fty>::NAN as $fty).minimum(-9.0).is_nan()); + $fassert!(<$fty>::NAN.minimum(9.0).is_nan()); + $fassert!(<$fty>::NAN.minimum(-9.0).is_nan()); $fassert!((9.0 as $fty).minimum(<$fty>::NAN).is_nan()); $fassert!((-9.0 as $fty).minimum(<$fty>::NAN).is_nan()); - $fassert!((<$fty>::NAN as $fty).minimum(<$fty>::NAN).is_nan()); + $fassert!(<$fty>::NAN.minimum(<$fty>::NAN).is_nan()); } #[test] fn maximum() { @@ -838,19 +838,19 @@ macro_rules! test_float { $fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive()); $fassert!((-0.0 as $fty).maximum(-9.0), -0.0); $fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative()); - $fassert!((<$fty>::INFINITY as $fty).maximum(9.0), <$fty>::INFINITY); + $fassert!(<$fty>::INFINITY.maximum(9.0), <$fty>::INFINITY); $fassert!((9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY); - $fassert!((<$fty>::INFINITY as $fty).maximum(-9.0), <$fty>::INFINITY); + $fassert!(<$fty>::INFINITY.maximum(-9.0), <$fty>::INFINITY); $fassert!((-9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY); - $fassert!((<$fty>::NEG_INFINITY as $fty).maximum(9.0), 9.0); + $fassert!(<$fty>::NEG_INFINITY.maximum(9.0), 9.0); $fassert!((9.0 as $fty).maximum(<$fty>::NEG_INFINITY), 9.0); - $fassert!((<$fty>::NEG_INFINITY as $fty).maximum(-9.0), -9.0); + $fassert!(<$fty>::NEG_INFINITY.maximum(-9.0), -9.0); $fassert!((-9.0 as $fty).maximum(<$fty>::NEG_INFINITY), -9.0); - $fassert!((<$fty>::NAN as $fty).maximum(9.0).is_nan()); - $fassert!((<$fty>::NAN as $fty).maximum(-9.0).is_nan()); + $fassert!(<$fty>::NAN.maximum(9.0).is_nan()); + $fassert!(<$fty>::NAN.maximum(-9.0).is_nan()); $fassert!((9.0 as $fty).maximum(<$fty>::NAN).is_nan()); $fassert!((-9.0 as $fty).maximum(<$fty>::NAN).is_nan()); - $fassert!((<$fty>::NAN as $fty).maximum(<$fty>::NAN).is_nan()); + $fassert!(<$fty>::NAN.maximum(<$fty>::NAN).is_nan()); } #[test] fn midpoint() { @@ -863,20 +863,17 @@ macro_rules! test_float { $fassert!((0.0 as $fty).midpoint(0.0), 0.0); $fassert!((-0.0 as $fty).midpoint(-0.0), -0.0); $fassert!((-5.0 as $fty).midpoint(5.0), 0.0); - $fassert!((<$fty>::MAX as $fty).midpoint(<$fty>::MIN), 0.0); - $fassert!((<$fty>::MIN as $fty).midpoint(<$fty>::MAX), -0.0); - $fassert!((<$fty>::MAX as $fty).midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.); - $fassert!((-<$fty>::MAX as $fty).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.); - $fassert!((<$fty>::MAX as $fty).midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.); - $fassert!( - (-<$fty>::MAX as $fty).midpoint(-<$fty>::MIN_POSITIVE), - -<$fty>::MAX / 2. - ); + $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN), 0.0); + $fassert!(<$fty>::MIN.midpoint(<$fty>::MAX), -0.0); + $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.); + $fassert!((-<$fty>::MAX).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.); + $fassert!(<$fty>::MAX.midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.); + $fassert!((-<$fty>::MAX).midpoint(-<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.); $fassert!((<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.); $fassert!((<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.); $fassert!((-<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.); $fassert!((-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.); - $fassert!((<$fty>::MAX as $fty).midpoint(<$fty>::MAX), <$fty>::MAX); + $fassert!(<$fty>::MAX.midpoint(<$fty>::MAX), <$fty>::MAX); $fassert!( (<$fty>::MIN_POSITIVE).midpoint(<$fty>::MIN_POSITIVE), <$fty>::MIN_POSITIVE @@ -885,16 +882,16 @@ macro_rules! test_float { (-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MIN_POSITIVE), -<$fty>::MIN_POSITIVE ); - $fassert!((<$fty>::MAX as $fty).midpoint(5.0), <$fty>::MAX / 2.0 + 2.5); - $fassert!((<$fty>::MAX as $fty).midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5); - $fassert!((<$fty>::INFINITY as $fty).midpoint(<$fty>::INFINITY), <$fty>::INFINITY); + $fassert!(<$fty>::MAX.midpoint(5.0), <$fty>::MAX / 2.0 + 2.5); + $fassert!(<$fty>::MAX.midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5); + $fassert!(<$fty>::INFINITY.midpoint(<$fty>::INFINITY), <$fty>::INFINITY); $fassert!( - (<$fty>::NEG_INFINITY as $fty).midpoint(<$fty>::NEG_INFINITY), + <$fty>::NEG_INFINITY.midpoint(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY ); - $fassert!((<$fty>::NAN as $fty).midpoint(1.0).is_nan()); + $fassert!(<$fty>::NAN.midpoint(1.0).is_nan()); $fassert!((1.0 as $fty).midpoint(<$fty>::NAN).is_nan()); - $fassert!((<$fty>::NAN as $fty).midpoint(<$fty>::NAN).is_nan()); + $fassert!(<$fty>::NAN.midpoint(<$fty>::NAN).is_nan()); // test if large differences in magnitude are still correctly computed. // NOTE: that because of how small x and y are, x + y can never overflow @@ -903,7 +900,7 @@ macro_rules! test_float { // be safely doubled, while j is significantly smaller. for i in <$fty>::MAX_EXP.saturating_sub(64)..<$fty>::MAX_EXP { for j in 0..64u8 { - let large = <$fty>::from(2.0f32).powi(i); + let large = (2.0 as $fty).powi(i); // a much smaller number, such that there is no chance of overflow to test // potential double rounding in midpoint's implementation. let small = (2.0 as $fty).powi(<$fty>::MAX_EXP - 1) @@ -918,6 +915,20 @@ macro_rules! test_float { } } #[test] + fn abs() { + $fassert!((-1.0 as $fty).abs(), 1.0); + $fassert!((1.0 as $fty).abs(), 1.0); + $fassert!(<$fty>::NEG_INFINITY.abs(), <$fty>::INFINITY); + $fassert!(<$fty>::INFINITY.abs(), <$fty>::INFINITY); + } + #[test] + fn copysign() { + $fassert!((1.0 as $fty).copysign(-2.0), -1.0); + $fassert!((-1.0 as $fty).copysign(2.0), 1.0); + $fassert!(<$fty>::INFINITY.copysign(-0.0), <$fty>::NEG_INFINITY); + $fassert!(<$fty>::NEG_INFINITY.copysign(0.0), <$fty>::INFINITY); + } + #[test] fn rem_euclid() { // FIXME: Use $fassert when rem_euclid becomes const assert!(<$fty>::INFINITY.rem_euclid((42.0 as $fty)).is_nan()); diff --git a/tests/ui/consts/const-eval/float_methods.rs b/tests/ui/consts/const-eval/float_methods.rs deleted file mode 100644 index 853f75825ac..00000000000 --- a/tests/ui/consts/const-eval/float_methods.rs +++ /dev/null @@ -1,46 +0,0 @@ -//@ run-pass -//! Tests the float intrinsics: min, max, abs, copysign - -#![feature(f16, f128)] - -const F16_MIN: f16 = 1.0_f16.min(0.5_f16); -const F16_MAX: f16 = 1.0_f16.max(0.5_f16); -const F16_ABS: f16 = (-1.0_f16).abs(); -const F16_COPYSIGN: f16 = 1.0_f16.copysign(-2.0_f16); - -const F32_MIN: f32 = 1.0_f32.min(0.5_f32); -const F32_MAX: f32 = 1.0_f32.max(0.5_f32); -const F32_ABS: f32 = (-1.0_f32).abs(); -const F32_COPYSIGN: f32 = 1.0_f32.copysign(-2.0_f32); - -const F64_MIN: f64 = 1.0_f64.min(0.5_f64); -const F64_MAX: f64 = 1.0_f64.max(0.5_f64); -const F64_ABS: f64 = (-1.0_f64).abs(); -const F64_COPYSIGN: f64 = 1.0_f64.copysign(-2.0_f64); - -const F128_MIN: f128 = 1.0_f128.min(0.5_f128); -const F128_MAX: f128 = 1.0_f128.max(0.5_f128); -const F128_ABS: f128 = (-1.0_f128).abs(); -const F128_COPYSIGN: f128 = 1.0_f128.copysign(-2.0_f128); - -fn main() { - assert_eq!(F16_MIN, 0.5); - assert_eq!(F16_MAX, 1.0); - assert_eq!(F16_ABS, 1.0); - assert_eq!(F16_COPYSIGN, -1.0); - - assert_eq!(F32_MIN, 0.5); - assert_eq!(F32_MAX, 1.0); - assert_eq!(F32_ABS, 1.0); - assert_eq!(F32_COPYSIGN, -1.0); - - assert_eq!(F64_MIN, 0.5); - assert_eq!(F64_MAX, 1.0); - assert_eq!(F64_ABS, 1.0); - assert_eq!(F64_COPYSIGN, -1.0); - - assert_eq!(F128_MIN, 0.5); - assert_eq!(F128_MAX, 1.0); - assert_eq!(F128_ABS, 1.0); - assert_eq!(F128_COPYSIGN, -1.0); -} -- cgit 1.4.1-3-g733a5 From bf52d1a8037c15ea67c21d857cb9ae6e2829931b Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Wed, 28 May 2025 10:23:38 +0200 Subject: ci: verify that codebuild jobs use ghcr.io --- src/ci/citool/src/jobs/tests.rs | 66 +++++++++++++++++++++++++++++++++++++++++ src/ci/citool/src/main.rs | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/ci/citool/src/jobs/tests.rs b/src/ci/citool/src/jobs/tests.rs index a489656fa5d..ed5444d4333 100644 --- a/src/ci/citool/src/jobs/tests.rs +++ b/src/ci/citool/src/jobs/tests.rs @@ -1,4 +1,8 @@ +use std::path::Path; + +use super::Job; use crate::jobs::{JobDatabase, load_job_db}; +use crate::{DOCKER_DIRECTORY, JOBS_YML_PATH, utils}; #[test] fn lookup_job_pattern() { @@ -62,3 +66,65 @@ fn check_pattern(db: &JobDatabase, pattern: &str, expected: &[&str]) { assert_eq!(jobs, expected); } + +/// Validate that CodeBuild jobs use Docker images from ghcr.io registry. +/// This is needed because otherwise from CodeBuild we get rate limited by Docker Hub. +fn validate_codebuild_image(job: &Job) -> anyhow::Result<()> { + let is_job_on_codebuild = job.codebuild.unwrap_or(false); + if !is_job_on_codebuild { + // Jobs in GitHub Actions don't get rate limited by Docker Hub. + return Ok(()); + } + + let image_name = job.image(); + // we hardcode host-x86_64 here, because in codebuild we only run jobs for this architecture. + let dockerfile_path = + Path::new(DOCKER_DIRECTORY).join("host-x86_64").join(&image_name).join("Dockerfile"); + + if !dockerfile_path.exists() { + return Err(anyhow::anyhow!( + "Dockerfile not found for CodeBuild job '{}' at path: {}", + job.name, + dockerfile_path.display() + )); + } + + let dockerfile_content = utils::read_to_string(&dockerfile_path)?; + + // Check if all FROM statement uses ghcr.io registry + let has_ghcr_from = dockerfile_content + .lines() + .filter(|line| line.trim_start().to_lowercase().starts_with("from ")) + .all(|line| line.contains("ghcr.io")); + + if !has_ghcr_from { + return Err(anyhow::anyhow!( + "CodeBuild job '{}' must use ghcr.io registry in its Dockerfile FROM statement. \ + Dockerfile path: {dockerfile_path:?}", + job.name, + )); + } + + Ok(()) +} + +#[test] +fn validate_jobs() { + let db = { + let default_jobs_file = Path::new(JOBS_YML_PATH); + let db_str = utils::read_to_string(default_jobs_file).unwrap(); + load_job_db(&db_str).expect("Failed to load job database") + }; + + let all_jobs = + db.pr_jobs.iter().chain(db.try_jobs.iter()).chain(db.auto_jobs.iter()).collect::>(); + + let errors: Vec = + all_jobs.into_iter().filter_map(|job| validate_codebuild_image(job).err()).collect(); + + if !errors.is_empty() { + let error_messages = + errors.into_iter().map(|e| format!("- {e}")).collect::>().join("\n"); + panic!("Job validation failed:\n{error_messages}"); + } +} diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 87ce09cfb23..bb73a5ef909 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -27,7 +27,7 @@ use crate::test_dashboard::generate_test_dashboard; use crate::utils::{load_env_var, output_details}; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); -const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker"); +pub const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker"); const JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../github-actions/jobs.yml"); struct GitHubContext { -- cgit 1.4.1-3-g733a5 From 457e84f4d8015af33a7d1fa4d3776a2dac67f3a8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 10:14:25 +0200 Subject: fix: Handle included files better in IDE layer This does not fully fix things, but it introduces a function that can be used to fix occurences. When using `to_def` functionality, the input node needs to come from the macro expanded include, not the real file that was included. This does unfortunately add more caller burden, but there is not really a way around it. --- .../rust-analyzer/crates/hir/src/semantics.rs | 37 ++++++++++-- .../crates/hir/src/semantics/source_to_def.rs | 24 ++++---- .../rust-analyzer/crates/ide/src/expand_macro.rs | 67 +++++++++++++++++----- 3 files changed, 97 insertions(+), 31 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 0dac64d6f2c..aea22545ed5 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -769,6 +769,31 @@ impl<'db> SemanticsImpl<'db> { }) } + /// Descends the token into the include expansion, if its file is an included file. + pub fn descend_token_into_include_expansion( + &self, + tok: InRealFile, + ) -> InFile { + let Some(include) = + self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, tok.file_id) + else { + return tok.into(); + }; + let span = self.db.real_span_map(tok.file_id).span_for_range(tok.value.text_range()); + let Some(InMacroFile { file_id, value: mut mapped_tokens }) = self.with_ctx(|ctx| { + Some( + ctx.cache + .get_or_insert_expansion(ctx.db, include) + .map_range_down(span)? + .map(SmallVec::<[_; 2]>::from_iter), + ) + }) else { + return tok.into(); + }; + // We should only get one result at most + mapped_tokens.pop().map_or_else(|| tok.into(), |(tok, _)| InFile::new(file_id.into(), tok)) + } + /// Maps a node down by mapping its first and last token down. pub fn descend_node_into_attributes(&self, node: N) -> SmallVec<[N; 1]> { // This might not be the correct way to do this, but it works for now @@ -1528,11 +1553,9 @@ impl<'db> SemanticsImpl<'db> { } pub fn resolve_macro_call2(&self, macro_call: InFile<&ast::MacroCall>) -> Option { - self.with_ctx(|ctx| { - ctx.macro_call_to_macro_call(macro_call) - .and_then(|call| macro_call_to_macro_id(ctx, call)) - .map(Into::into) - }) + self.to_def2(macro_call) + .and_then(|call| self.with_ctx(|ctx| macro_call_to_macro_id(ctx, call))) + .map(Into::into) } pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool { @@ -1647,6 +1670,10 @@ impl<'db> SemanticsImpl<'db> { T::to_def(self, src) } + pub fn to_def2(&self, src: InFile<&T>) -> Option { + T::to_def(self, src) + } + fn file_to_module_defs(&self, file: FileId) -> impl Iterator { self.with_ctx(|ctx| ctx.file_to_def(file).to_owned()).into_iter().map(Module::from) } 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 172af456d92..7f6c9af4740 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 @@ -399,19 +399,6 @@ impl SourceToDefCtx<'_, '_> { Some((container, label?)) } - pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option { - let map = self.dyn_map(src)?; - map[keys::ATTR_MACRO_CALL].get(&AstPtr::new(src.value)).copied() - } - - pub(super) fn macro_call_to_macro_call( - &mut self, - src: InFile<&ast::MacroCall>, - ) -> Option { - let map = self.dyn_map(src)?; - map[keys::MACRO_CALL].get(&AstPtr::new(src.value)).copied() - } - /// (AttrId, derive attribute call id, derive call ids) pub(super) fn attr_to_derive_macro_call( &mut self, @@ -449,6 +436,17 @@ impl SourceToDefCtx<'_, '_> { .or_insert_with(|| container.child_by_source(db, file_id)) } + pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option { + self.to_def(src, keys::ATTR_MACRO_CALL) + } + + pub(super) fn macro_call_to_macro_call( + &mut self, + src: InFile<&ast::MacroCall>, + ) -> Option { + self.to_def(src, keys::MACRO_CALL) + } + pub(super) fn type_param_to_def( &mut self, src: InFile<&ast::TypeParam>, diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index f8f9378b9e9..7c396339c14 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -1,10 +1,10 @@ use hir::db::ExpandDatabase; -use hir::{ExpandResult, InFile, Semantics}; +use hir::{ExpandResult, InFile, InRealFile, Semantics}; use ide_db::{ FileId, RootDatabase, base_db::Crate, helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, }; -use span::{Edition, SpanMap, SyntaxContext, TextRange, TextSize}; +use span::{SpanMap, SyntaxContext, TextRange, TextSize}; use stdx::format_to; use syntax::{AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, ast, ted}; @@ -26,8 +26,9 @@ pub struct ExpandedMacro { // ![Expand Macro Recursively](https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif) pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option { let sema = Semantics::new(db); - let file = sema.parse_guess_edition(position.file_id); - let krate = sema.file_to_module_def(position.file_id)?.krate().into(); + let file_id = sema.attach_first_edition(position.file_id)?; + let file = sema.parse(file_id); + let krate = sema.file_to_module_def(file_id.file_id(db))?.krate().into(); let tok = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { SyntaxKind::IDENT => 1, @@ -86,7 +87,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< return derive; } - let mut anc = tok.parent_ancestors(); + let mut anc = sema + .descend_token_into_include_expansion(InRealFile::new(file_id, tok)) + .value + .parent_ancestors(); let mut span_map = SpanMap::empty(); let mut error = String::new(); let (name, expanded, kind) = loop { @@ -95,14 +99,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< if let Some(item) = ast::Item::cast(node.clone()) { if let Some(def) = sema.resolve_attr_macro_call(&item) { break ( - def.name(db) - .display( - db, - sema.attach_first_edition(position.file_id) - .map(|it| it.edition(db)) - .unwrap_or(Edition::CURRENT), - ) - .to_string(), + def.name(db).display(db, file_id.edition(db)).to_string(), expand_macro_recur(&sema, &item, &mut error, &mut span_map, TextSize::new(0))?, SyntaxKind::MACRO_ITEMS, ); @@ -759,4 +756,48 @@ fn test() { "<>hi""#]], ); } + + #[test] + fn in_included() { + check( + r#" +//- minicore: include +//- /main.rs crate:main +include!("./included.rs"); +//- /included.rs +macro_rules! foo { + () => { fn item() {} }; +} +foo$0!(); +"#, + expect![[r#" + foo! + fn item(){}"#]], + ); + } + + #[test] + fn include() { + check( + r#" +//- minicore: include +//- /main.rs crate:main +include$0!("./included.rs"); +//- /included.rs +macro_rules! foo { + () => { fn item() {} }; +} +foo(); +"#, + expect![[r#" + include! + macro_rules! foo { + () => { + fn item(){} + + }; + } + foo();"#]], + ); + } } -- cgit 1.4.1-3-g733a5 From 8231d888cfc8d4b8b2e47c0489d17d7f0bbbb169 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 11:12:28 +0200 Subject: feat: Desugar assist for `let pat = expr?;` -> `let else` --- .../ide-assists/src/handlers/desugar_try_expr.rs | 281 +++++++++++++++++++++ .../src/handlers/replace_try_expr_with_match.rs | 148 ----------- .../rust-analyzer/crates/ide-assists/src/lib.rs | 4 +- .../crates/ide-assists/src/tests/generated.rs | 62 +++-- .../syntax/src/ast/syntax_factory/constructors.rs | 12 + 5 files changed, 336 insertions(+), 171 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs delete mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs new file mode 100644 index 00000000000..efadde9e364 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs @@ -0,0 +1,281 @@ +use std::iter; + +use ide_db::{ + assists::{AssistId, ExprFillDefaultMode}, + ty_filter::TryEnum, +}; +use syntax::{ + AstNode, T, + ast::{ + self, + edit::{AstNodeEdit, IndentLevel}, + make, + syntax_factory::SyntaxFactory, + }, +}; + +use crate::assist_context::{AssistContext, Assists}; + +// Assist: desugar_try_expr_match +// +// Replaces a `try` expression with a `match` expression. +// +// ``` +// # //- minicore: try, option +// fn handle() { +// let pat = Some(true)$0?; +// } +// ``` +// -> +// ``` +// fn handle() { +// let pat = match Some(true) { +// Some(it) => it, +// None => return None, +// }; +// } +// ``` + +// Assist: desugar_try_expr_let_else +// +// Replaces a `try` expression with a `let else` statement. +// +// ``` +// # //- minicore: try, option +// fn handle() { +// let pat = Some(true)$0?; +// } +// ``` +// -> +// ``` +// fn handle() { +// let Some(pat) = Some(true) else { +// return None; +// }; +// } +// ``` +pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let question_tok = ctx.find_token_syntax_at_offset(T![?])?; + let try_expr = question_tok.parent().and_then(ast::TryExpr::cast)?; + + let expr = try_expr.expr()?; + let expr_type_info = ctx.sema.type_of_expr(&expr)?; + + let try_enum = TryEnum::from_ty(&ctx.sema, &expr_type_info.original)?; + + let target = try_expr.syntax().text_range(); + acc.add( + AssistId::refactor_rewrite("desugar_try_expr_match"), + "Replace try expression with match", + target, + |edit| { + let sad_pat = match try_enum { + TryEnum::Option => make::path_pat(make::ext::ident_path("None")), + TryEnum::Result => make::tuple_struct_pat( + make::ext::ident_path("Err"), + iter::once(make::path_pat(make::ext::ident_path("err"))), + ) + .into(), + }; + let sad_expr = match try_enum { + TryEnum::Option => { + make::expr_return(Some(make::expr_path(make::ext::ident_path("None")))) + } + TryEnum::Result => make::expr_return(Some( + make::expr_call( + make::expr_path(make::ext::ident_path("Err")), + make::arg_list(iter::once(make::expr_path(make::ext::ident_path("err")))), + ) + .into(), + )), + }; + + let happy_arm = make::match_arm( + try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()), + None, + make::expr_path(make::ext::ident_path("it")), + ); + let sad_arm = make::match_arm(sad_pat, None, sad_expr); + + let match_arm_list = make::match_arm_list([happy_arm, sad_arm]); + + let expr_match = make::expr_match(expr.clone(), match_arm_list) + .indent(IndentLevel::from_node(try_expr.syntax())); + + edit.replace_ast::(try_expr.clone().into(), expr_match.into()); + }, + ); + + if let Some(let_stmt) = try_expr.syntax().parent().and_then(ast::LetStmt::cast) { + if let_stmt.let_else().is_none() { + let pat = let_stmt.pat()?; + acc.add( + AssistId::refactor_rewrite("desugar_try_expr_let_else"), + "Replace try expression with let else", + target, + |builder| { + let make = SyntaxFactory::with_mappings(); + let mut editor = builder.make_editor(let_stmt.syntax()); + + let indent_level = IndentLevel::from_node(let_stmt.syntax()); + let new_let_stmt = make.let_else_stmt( + try_enum.happy_pattern(pat), + let_stmt.ty(), + expr, + make.block_expr( + iter::once( + make.expr_stmt( + make.expr_return(Some(match try_enum { + TryEnum::Option => make.expr_path(make.ident_path("None")), + TryEnum::Result => make + .expr_call( + make.expr_path(make.ident_path("Err")), + make.arg_list(iter::once( + match ctx.config.expr_fill_default { + ExprFillDefaultMode::Todo => make + .expr_macro( + make.ident_path("todo"), + make.token_tree( + syntax::SyntaxKind::L_PAREN, + [], + ), + ) + .into(), + ExprFillDefaultMode::Underscore => { + make.expr_underscore().into() + } + ExprFillDefaultMode::Default => make + .expr_macro( + make.ident_path("todo"), + make.token_tree( + syntax::SyntaxKind::L_PAREN, + [], + ), + ) + .into(), + }, + )), + ) + .into(), + })) + .indent(indent_level + 1) + .into(), + ) + .into(), + ), + None, + ) + .indent(indent_level), + ); + editor.replace(let_stmt.syntax(), new_let_stmt.syntax()); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); + }, + ); + } + } + Some(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::{check_assist, check_assist_by_label, check_assist_not_applicable}; + + #[test] + fn test_desugar_try_expr_not_applicable() { + check_assist_not_applicable( + desugar_try_expr, + r#" + fn test() { + let pat: u32 = 25$0; + } + "#, + ); + } + + #[test] + fn test_desugar_try_expr_option() { + check_assist( + desugar_try_expr, + r#" +//- minicore: try, option +fn test() { + let pat = Some(true)$0?; +} + "#, + r#" +fn test() { + let pat = match Some(true) { + Some(it) => it, + None => return None, + }; +} + "#, + ); + } + + #[test] + fn test_desugar_try_expr_result() { + check_assist( + desugar_try_expr, + r#" +//- minicore: try, from, result +fn test() { + let pat = Ok(true)$0?; +} + "#, + r#" +fn test() { + let pat = match Ok(true) { + Ok(it) => it, + Err(err) => return Err(err), + }; +} + "#, + ); + } + + #[test] + fn test_desugar_try_expr_option_let_else() { + check_assist_by_label( + desugar_try_expr, + r#" +//- minicore: try, option +fn test() { + let pat = Some(true)$0?; +} + "#, + r#" +fn test() { + let Some(pat) = Some(true) else { + return None; + }; +} + "#, + "Replace try expression with let else", + ); + } + + #[test] + fn test_desugar_try_expr_result_let_else() { + check_assist_by_label( + desugar_try_expr, + r#" +//- minicore: try, from, result +fn test() { + let pat = Ok(true)$0?; +} + "#, + r#" +fn test() { + let Ok(pat) = Ok(true) else { + return Err(todo!()); + }; +} + "#, + "Replace try expression with let else", + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs deleted file mode 100644 index c6e864fcfdb..00000000000 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::iter; - -use ide_db::{assists::AssistId, ty_filter::TryEnum}; -use syntax::{ - AstNode, T, - ast::{ - self, - edit::{AstNodeEdit, IndentLevel}, - make, - }, -}; - -use crate::assist_context::{AssistContext, Assists}; - -// Assist: replace_try_expr_with_match -// -// Replaces a `try` expression with a `match` expression. -// -// ``` -// # //- minicore: try, option -// fn handle() { -// let pat = Some(true)$0?; -// } -// ``` -// -> -// ``` -// fn handle() { -// let pat = match Some(true) { -// Some(it) => it, -// None => return None, -// }; -// } -// ``` -pub(crate) fn replace_try_expr_with_match( - acc: &mut Assists, - ctx: &AssistContext<'_>, -) -> Option<()> { - let qm_kw = ctx.find_token_syntax_at_offset(T![?])?; - let qm_kw_parent = qm_kw.parent().and_then(ast::TryExpr::cast)?; - - let expr = qm_kw_parent.expr()?; - let expr_type_info = ctx.sema.type_of_expr(&expr)?; - - let try_enum = TryEnum::from_ty(&ctx.sema, &expr_type_info.original)?; - - let target = qm_kw_parent.syntax().text_range(); - acc.add( - AssistId::refactor_rewrite("replace_try_expr_with_match"), - "Replace try expression with match", - target, - |edit| { - let sad_pat = match try_enum { - TryEnum::Option => make::path_pat(make::ext::ident_path("None")), - TryEnum::Result => make::tuple_struct_pat( - make::ext::ident_path("Err"), - iter::once(make::path_pat(make::ext::ident_path("err"))), - ) - .into(), - }; - let sad_expr = match try_enum { - TryEnum::Option => { - make::expr_return(Some(make::expr_path(make::ext::ident_path("None")))) - } - TryEnum::Result => make::expr_return(Some( - make::expr_call( - make::expr_path(make::ext::ident_path("Err")), - make::arg_list(iter::once(make::expr_path(make::ext::ident_path("err")))), - ) - .into(), - )), - }; - - let happy_arm = make::match_arm( - try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()), - None, - make::expr_path(make::ext::ident_path("it")), - ); - let sad_arm = make::match_arm(sad_pat, None, sad_expr); - - let match_arm_list = make::match_arm_list([happy_arm, sad_arm]); - - let expr_match = make::expr_match(expr, match_arm_list) - .indent(IndentLevel::from_node(qm_kw_parent.syntax())); - edit.replace_ast::(qm_kw_parent.into(), expr_match.into()); - }, - ) -} - -#[cfg(test)] -mod tests { - use super::*; - - use crate::tests::{check_assist, check_assist_not_applicable}; - - #[test] - fn test_replace_try_expr_with_match_not_applicable() { - check_assist_not_applicable( - replace_try_expr_with_match, - r#" - fn test() { - let pat: u32 = 25$0; - } - "#, - ); - } - - #[test] - fn test_replace_try_expr_with_match_option() { - check_assist( - replace_try_expr_with_match, - r#" -//- minicore: try, option -fn test() { - let pat = Some(true)$0?; -} - "#, - r#" -fn test() { - let pat = match Some(true) { - Some(it) => it, - None => return None, - }; -} - "#, - ); - } - - #[test] - fn test_replace_try_expr_with_match_result() { - check_assist( - replace_try_expr_with_match, - r#" -//- minicore: try, from, result -fn test() { - let pat = Ok(true)$0?; -} - "#, - r#" -fn test() { - let pat = match Ok(true) { - Ok(it) => it, - Err(err) => return Err(err), - }; -} - "#, - ); - } -} 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 2395091b6f2..c2604432032 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -139,6 +139,7 @@ mod handlers { mod destructure_struct_binding; mod destructure_tuple_binding; mod desugar_doc_comment; + mod desugar_try_expr; mod expand_glob_import; mod expand_rest_pattern; mod extract_expressions_from_format_string; @@ -214,7 +215,6 @@ mod handlers { mod replace_named_generic_with_impl; mod replace_qualified_name_with_use; mod replace_string_with_char; - mod replace_try_expr_with_match; mod replace_turbofish_with_explicit_type; mod sort_items; mod split_import; @@ -273,6 +273,7 @@ mod handlers { destructure_struct_binding::destructure_struct_binding, destructure_tuple_binding::destructure_tuple_binding, desugar_doc_comment::desugar_doc_comment, + desugar_try_expr::desugar_try_expr, expand_glob_import::expand_glob_import, expand_glob_import::expand_glob_reexport, expand_rest_pattern::expand_rest_pattern, @@ -354,7 +355,6 @@ mod handlers { replace_method_eager_lazy::replace_with_lazy_method, replace_named_generic_with_impl::replace_named_generic_with_impl, replace_qualified_name_with_use::replace_qualified_name_with_use, - replace_try_expr_with_match::replace_try_expr_with_match, replace_turbofish_with_explicit_type::replace_turbofish_with_explicit_type, sort_items::sort_items, split_import::split_import, 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 76134acb36e..72f7195cbd7 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 @@ -929,6 +929,47 @@ comment"] ) } +#[test] +fn doctest_desugar_try_expr_let_else() { + check_doc_test( + "desugar_try_expr_let_else", + r#####" +//- minicore: try, option +fn handle() { + let pat = Some(true)$0?; +} +"#####, + r#####" +fn handle() { + let Some(pat) = Some(true) else { + return None; + }; +} +"#####, + ) +} + +#[test] +fn doctest_desugar_try_expr_match() { + check_doc_test( + "desugar_try_expr_match", + r#####" +//- minicore: try, option +fn handle() { + let pat = Some(true)$0?; +} +"#####, + r#####" +fn handle() { + let pat = match Some(true) { + Some(it) => it, + None => return None, + }; +} +"#####, + ) +} + #[test] fn doctest_expand_glob_import() { check_doc_test( @@ -3096,27 +3137,6 @@ fn main() { ) } -#[test] -fn doctest_replace_try_expr_with_match() { - check_doc_test( - "replace_try_expr_with_match", - r#####" -//- minicore: try, option -fn handle() { - let pat = Some(true)$0?; -} -"#####, - r#####" -fn handle() { - let pat = match Some(true) { - Some(it) => it, - None => return None, - }; -} -"#####, - ) -} - #[test] fn doctest_replace_turbofish_with_explicit_type() { check_doc_test( diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index 8dee3964d44..429e51ba362 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -585,6 +585,18 @@ impl SyntaxFactory { ast } + pub fn expr_underscore(&self) -> ast::UnderscoreExpr { + let ast::Expr::UnderscoreExpr(ast) = make::ext::expr_underscore().clone_for_update() else { + unreachable!() + }; + + if let Some(mut mapping) = self.mappings() { + SyntaxMappingBuilder::new(ast.syntax().clone()).finish(&mut mapping); + } + + ast + } + pub fn expr_if( &self, condition: ast::Expr, -- cgit 1.4.1-3-g733a5 From 550aed825b3a630b5b2bd235e193bfce065268c2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 26 May 2025 10:38:02 +0000 Subject: Use `builin_index` instead of hand-rolling it --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 3 +-- compiler/rustc_hir_typeck/src/expr.rs | 10 ++-------- compiler/rustc_pattern_analysis/src/rustc.rs | 6 +++--- src/tools/clippy/clippy_lints/src/index_refutable_slice.rs | 5 ++--- src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs | 4 ++-- src/tools/clippy/clippy_utils/src/consts.rs | 4 +--- 6 files changed, 11 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 06c5e518fc6..0f17cbc0ce8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1048,8 +1048,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), match ty.kind() { ty::Adt(adt_def, ..) => adt_def.did().is_local(), // Arrays and slices use the inner type's `ConstParamTy`. - ty::Array(ty, ..) => ty_is_local(*ty), - ty::Slice(ty) => ty_is_local(*ty), + ty::Array(ty, ..) | ty::Slice(ty) => ty_is_local(*ty), // `&` references use the inner type's `ConstParamTy`. // `&mut` are not supported. ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1d86f7d223c..082ddac7e5a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1793,10 +1793,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let element_ty = if !args.is_empty() { let coerce_to = expected .to_option(self) - .and_then(|uty| match *self.try_structurally_resolve_type(expr.span, uty).kind() { - ty::Array(ty, _) | ty::Slice(ty) => Some(ty), - _ => None, - }) + .and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index()) .unwrap_or_else(|| self.next_ty_var(expr.span)); let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args); assert_eq!(self.diverges.get(), Diverges::Maybe); @@ -1874,10 +1871,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let uty = match expected { - ExpectHasType(uty) => match *uty.kind() { - ty::Array(ty, _) | ty::Slice(ty) => Some(ty), - _ => None, - }, + ExpectHasType(uty) => uty.builtin_index(), _ => None, }; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d9f1888bfd9..46ced7500ea 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -249,12 +249,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { ty::Ref(_, rty, _) => reveal_and_alloc(cx, once(*rty)), _ => bug!("Unexpected type for `Ref` constructor: {ty:?}"), }, - Slice(slice) => match *ty.kind() { - ty::Slice(ty) | ty::Array(ty, _) => { + Slice(slice) => match ty.builtin_index() { + Some(ty) => { let arity = slice.arity(); reveal_and_alloc(cx, (0..arity).map(|_| ty)) } - _ => bug!("bad slice pattern {:?} {:?}", ctor, ty), + None => bug!("bad slice pattern {:?} {:?}", ctor, ty), }, DerefPattern(pointee_ty) => reveal_and_alloc(cx, once(pointee_ty.inner())), Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..) 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 0b1cae30ca5..3d131a7825a 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -12,7 +12,6 @@ use rustc_hir::HirId; use rustc_hir::intravisit::{self, Visitor}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::symbol::Ident; @@ -109,11 +108,11 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap for TupleArrayConversions { } fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) { - let (ty::Array(ty, _) | ty::Slice(ty)) = cx.typeck_results().expr_ty(expr).kind() else { + let Some(ty) = cx.typeck_results().expr_ty(expr).builtin_index() else { unreachable!("`expr` must be an array or slice due to `ExprKind::Array`"); }; @@ -85,7 +85,7 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: & ExprKind::Path(_) => Some(elements.iter().collect()), _ => None, }) - && all_bindings_are_for_conv(cx, &[*ty], expr, elements, &locals, ToType::Array) + && all_bindings_are_for_conv(cx, &[ty], expr, elements, &locals, ToType::Array) && !is_from_proc_macro(cx, expr) { span_lint_and_help( diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 6f5b0ec54cd..1ec5d11384f 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -235,9 +235,7 @@ impl Constant<'_> { _ => None, }, (Self::Vec(l), Self::Vec(r)) => { - let (ty::Array(cmp_type, _) | ty::Slice(cmp_type)) = *cmp_type.kind() else { - return None; - }; + let cmp_type = cmp_type.builtin_index()?; iter::zip(l, r) .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) .find(|r| r.is_none_or(|o| o != Ordering::Equal)) -- cgit 1.4.1-3-g733a5 From 0dd5722d6790be37b310c2e578be4f162d2be6ef Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Fri, 16 May 2025 22:49:00 +0200 Subject: Test(fs): Fix test_eq_windows_file_type for Windows 7 Would otherwise fail on: ``` thread 'fs::tests::test_eq_windows_file_type' panicked at library/std/src/test_helpers.rs:53:20: called `Result::unwrap()` on an `Err` value: Os { code: 5, kind: PermissionDenied, message: "Access is denied." } ``` This came from the read-only attribute set on the test file. In order to fix this, instead of simply disabling the test, the attribute is reset before the test's end so it may still run successfully. Signed-off-by: Paul Mabileau --- library/std/src/fs/tests.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 8da6d75b73e..c81e3af2f0d 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1782,8 +1782,30 @@ fn test_eq_windows_file_type() { // Change the readonly attribute of one file. let mut perms = file1.metadata().unwrap().permissions(); perms.set_readonly(true); - file1.set_permissions(perms).unwrap(); + file1.set_permissions(perms.clone()).unwrap(); + #[cfg(target_vendor = "win7")] + let _g = ReadonlyGuard { file: &file1, perms }; assert_eq!(file1.metadata().unwrap().file_type(), file2.metadata().unwrap().file_type()); + + // Reset the attribute before the `TmpDir`'s drop that removes the + // associated directory, which fails with a `PermissionDenied` error when + // running under Windows 7. + #[cfg(target_vendor = "win7")] + struct ReadonlyGuard<'f> { + file: &'f File, + perms: fs::Permissions, + } + #[cfg(target_vendor = "win7")] + impl<'f> Drop for ReadonlyGuard<'f> { + fn drop(&mut self) { + self.perms.set_readonly(false); + let res = self.file.set_permissions(self.perms.clone()); + + if !thread::panicking() { + res.unwrap(); + } + } + } } /// Regression test for https://github.com/rust-lang/rust/issues/50619. -- cgit 1.4.1-3-g733a5 From 9389daab8d37298587305127f587e4fdd0f20598 Mon Sep 17 00:00:00 2001 From: David Klank <155117116+davidjsonn@users.noreply.github.com> Date: Wed, 28 May 2025 13:50:38 +0300 Subject: replace TraitRef link memory.md --- src/doc/rustc-dev-guide/src/memory.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md index eeb4a813980..f766a51898e 100644 --- a/src/doc/rustc-dev-guide/src/memory.md +++ b/src/doc/rustc-dev-guide/src/memory.md @@ -63,7 +63,7 @@ represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). [`mk_args`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.mk_args [adtdefid]: ./ty_module/generic_arguments.md#adtdef-and-defid [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html -[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html +[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html [`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.TyKind.html [traits]: ./traits/resolution.md -- cgit 1.4.1-3-g733a5 From bcebf58accb50f2252a1bf728a8da2316a1c1e48 Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 28 May 2025 13:04:37 +0200 Subject: interpret/allocation: make alloc fn be FnOnce --- compiler/rustc_middle/src/mir/interpret/allocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index f17747558fc..dd55d039794 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -512,7 +512,7 @@ impl Allocation { pub fn adjust_from_tcx<'tcx, Prov: Provenance, Bytes: AllocBytes>( &self, cx: &impl HasDataLayout, - mut alloc_bytes: impl FnMut(&[u8], Align) -> InterpResult<'tcx, Bytes>, + alloc_bytes: impl FnOnce(&[u8], Align) -> InterpResult<'tcx, Bytes>, mut adjust_ptr: impl FnMut(Pointer) -> InterpResult<'tcx, Pointer>, ) -> InterpResult<'tcx, Allocation> { // Copy the data. -- cgit 1.4.1-3-g733a5 From 3a736e2726dcd4cb534eaf64b25196fa45a26a03 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 May 2025 12:17:18 +0000 Subject: Handle e2021 precise capturing of unsafe binder --- compiler/rustc_middle/src/ty/closure.rs | 4 ++++ compiler/rustc_mir_build/src/builder/expr/as_place.rs | 4 ++-- tests/ui/unsafe-binders/cat-projection.rs | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index ff9096695d4..df67bb505a6 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -117,6 +117,10 @@ impl<'tcx> CapturedPlace<'tcx> { } }, + HirProjectionKind::UnwrapUnsafeBinder => { + write!(&mut symbol, "__unwrap").unwrap(); + } + // Ignore derefs for now, as they are likely caused by // autoderefs that don't appear in the original code. HirProjectionKind::Deref => {} diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 830a129c585..f8c64d7d13e 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -101,12 +101,12 @@ fn convert_to_hir_projections_and_truncate_for_capture( variant = Some(*idx); continue; } + ProjectionElem::UnwrapUnsafeBinder(_) => HirProjectionKind::UnwrapUnsafeBinder, // These do not affect anything, they just make sure we know the right type. ProjectionElem::OpaqueCast(_) | ProjectionElem::Subtype(..) => continue, ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::UnwrapUnsafeBinder(_) => { + | ProjectionElem::Subslice { .. } => { // We don't capture array-access projections. // We can stop here as arrays are captured completely. break; diff --git a/tests/ui/unsafe-binders/cat-projection.rs b/tests/ui/unsafe-binders/cat-projection.rs index dd7a78d59b3..0ce8579a688 100644 --- a/tests/ui/unsafe-binders/cat-projection.rs +++ b/tests/ui/unsafe-binders/cat-projection.rs @@ -1,3 +1,6 @@ +//@ revisions: e2015 e2021 +//@[e2015] edition: 2015 +//@[e2021] edition: 2021 //@ check-pass #![feature(unsafe_binders)] -- cgit 1.4.1-3-g733a5 From d88641f8bc4c9ad1e0f528f0834c14da302be447 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 28 May 2025 15:36:32 +0300 Subject: rustbook: Bump versions of `onig` and `onig_sys` This fixes the build on GCC 15 --- src/tools/rustbook/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 07c5106331b..8893846b5fa 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -1026,11 +1026,11 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "onig" -version = "6.4.0" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.0", "libc", "once_cell", "onig_sys", @@ -1038,9 +1038,9 @@ dependencies = [ [[package]] name = "onig_sys" -version = "69.8.1" +version = "69.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc" dependencies = [ "cc", "pkg-config", -- cgit 1.4.1-3-g733a5 From 2e99a880e22f5a1f3800e1a26828b188204d037e Mon Sep 17 00:00:00 2001 From: Patrick-6 Date: Wed, 28 May 2025 15:12:56 +0200 Subject: Add diagnostic items to sys::Mutex --- compiler/rustc_span/src/symbol.rs | 3 +++ library/std/src/sys/sync/mutex/futex.rs | 3 +++ library/std/src/sys/sync/mutex/pthread.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 0447713fb05..58091bc32d2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2071,6 +2071,9 @@ symbols! { sym, sync, synthetic, + sys_mutex_lock, + sys_mutex_try_lock, + sys_mutex_unlock, t32, target, target_abi, diff --git a/library/std/src/sys/sync/mutex/futex.rs b/library/std/src/sys/sync/mutex/futex.rs index ce9b2daa5f8..01e91a6294a 100644 --- a/library/std/src/sys/sync/mutex/futex.rs +++ b/library/std/src/sys/sync/mutex/futex.rs @@ -19,11 +19,13 @@ impl Mutex { } #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")] pub fn try_lock(&self) -> bool { self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok() } #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")] pub fn lock(&self) { if self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_err() { self.lock_contended(); @@ -80,6 +82,7 @@ impl Mutex { } #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")] pub unsafe fn unlock(&self) { if self.futex.swap(UNLOCKED, Release) == CONTENDED { // We only wake up one thread. When that thread locks the mutex, it diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs index 75b4b9c6dad..52588a7899a 100644 --- a/library/std/src/sys/sync/mutex/pthread.rs +++ b/library/std/src/sys/sync/mutex/pthread.rs @@ -28,6 +28,7 @@ impl Mutex { } #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")] pub fn lock(&self) { // SAFETY: we call `init` above, therefore reentrant locking is safe. // In `drop` we ensure that the mutex is not destroyed while locked. @@ -35,6 +36,7 @@ impl Mutex { } #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")] pub unsafe fn unlock(&self) { // SAFETY: the mutex can only be locked if it is already initialized // and we observed this initialization since we observed the locking. @@ -42,6 +44,7 @@ impl Mutex { } #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")] pub fn try_lock(&self) -> bool { // SAFETY: we call `init` above, therefore reentrant locking is safe. // In `drop` we ensure that the mutex is not destroyed while locked. -- cgit 1.4.1-3-g733a5 From 149b5b2567535af761d16ed388b653740db7a457 Mon Sep 17 00:00:00 2001 From: Patrick-6 Date: Wed, 28 May 2025 15:13:38 +0200 Subject: Make pthread Mutex internals less public --- library/std/src/sys/sync/mutex/pthread.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs index 52588a7899a..1d442248374 100644 --- a/library/std/src/sys/sync/mutex/pthread.rs +++ b/library/std/src/sys/sync/mutex/pthread.rs @@ -6,7 +6,7 @@ use crate::sys::pal::sync as pal; use crate::sys::sync::OnceBox; pub struct Mutex { - pub pal: OnceBox, + pub(in crate::sys::sync) pal: OnceBox, } impl Mutex { -- cgit 1.4.1-3-g733a5 From 9f12748086823f58bc03ab5f4390e98a69991127 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Sun, 2 Feb 2025 11:26:20 +0100 Subject: GCI: Check where-clauses for well-formedness at the def site --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 41 +++++++++++++++++----- .../generic-const-items/def-site-predicates-wf.rs | 9 +++++ .../def-site-predicates-wf.stderr | 13 +++++++ 3 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 tests/ui/generic-const-items/def-site-predicates-wf.rs create mode 100644 tests/ui/generic-const-items/def-site-predicates-wf.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 06c5e518fc6..5070ab138c5 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -298,11 +298,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() check_item_fn(tcx, def_id, ident, item.span, sig.decl) } hir::ItemKind::Static(_, ty, ..) => { - check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) - } - hir::ItemKind::Const(_, ty, ..) => { - check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) + check_static_item(tcx, def_id, ty.span, UnsizedHandling::Forbid) } + hir::ItemKind::Const(_, ty, ..) => check_const_item(tcx, def_id, ty.span, item.span), hir::ItemKind::Struct(_, _, hir_generics) => { let res = check_type_defn(tcx, item, false); check_variances_for_type_defn(tcx, item, hir_generics); @@ -366,7 +364,7 @@ fn check_foreign_item<'tcx>( check_item_fn(tcx, def_id, item.ident, item.span, sig.decl) } hir::ForeignItemKind::Static(ty, ..) => { - check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail) + check_static_item(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail) } hir::ForeignItemKind::Type => Ok(()), } @@ -1331,14 +1329,13 @@ enum UnsizedHandling { AllowIfForeignTail, } -fn check_item_type( +#[instrument(level = "debug", skip(tcx, ty_span, unsized_handling))] +fn check_static_item( tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, unsized_handling: UnsizedHandling, ) -> Result<(), ErrorGuaranteed> { - debug!("check_item_type: {:?}", item_id); - enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| { let ty = tcx.type_of(item_id).instantiate_identity(); let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty); @@ -1388,6 +1385,34 @@ fn check_item_type( }) } +fn check_const_item( + tcx: TyCtxt<'_>, + def_id: LocalDefId, + ty_span: Span, + item_span: Span, +) -> Result<(), ErrorGuaranteed> { + enter_wf_checking_ctxt(tcx, ty_span, def_id, |wfcx| { + let ty = tcx.type_of(def_id).instantiate_identity(); + let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty); + + wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into()); + wfcx.register_bound( + traits::ObligationCause::new( + ty_span, + wfcx.body_def_id, + ObligationCauseCode::SizedConstOrStatic, + ), + wfcx.param_env, + ty, + tcx.require_lang_item(LangItem::Sized, None), + ); + + check_where_clauses(wfcx, item_span, def_id); + + Ok(()) + }) +} + #[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/tests/ui/generic-const-items/def-site-predicates-wf.rs b/tests/ui/generic-const-items/def-site-predicates-wf.rs new file mode 100644 index 00000000000..39cdcc304f3 --- /dev/null +++ b/tests/ui/generic-const-items/def-site-predicates-wf.rs @@ -0,0 +1,9 @@ +//! Ensure that we check the predicates for well-formedness at the definition site. +#![feature(generic_const_items)] +#![expect(incomplete_features)] + +const _: () = () +where + Vec: Sized; //~ ERROR the size for values of type `str` cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/generic-const-items/def-site-predicates-wf.stderr b/tests/ui/generic-const-items/def-site-predicates-wf.stderr new file mode 100644 index 00000000000..62db089fd55 --- /dev/null +++ b/tests/ui/generic-const-items/def-site-predicates-wf.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/def-site-predicates-wf.rs:7:15 + | +LL | Vec: Sized; + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From 2593df8837f330301b5679e33efd54f36ba43c43 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 May 2025 15:06:08 +0200 Subject: core: unstably expose atomic_compare_exchange so stdarch can use it --- library/core/src/sync/atomic.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index bd5a58d74ba..6bc6bee682d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -3885,10 +3885,13 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { } } +/// Publicly exposed for stdarch; nobody else should use this. #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_compare_exchange( +#[unstable(feature = "core_intrinsics", issue = "none")] +#[doc(hidden)] +pub unsafe fn atomic_compare_exchange( dst: *mut T, old: T, new: T, -- cgit 1.4.1-3-g733a5 From 467eeabbb5e876abc6bf552670199695172ad07a Mon Sep 17 00:00:00 2001 From: beetrees Date: Sun, 9 Mar 2025 19:03:12 +0000 Subject: Stabilise `repr128` --- .../rustc_error_codes/src/error_codes/E0658.md | 12 +- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_hir_analysis/src/check/check.rs | 15 +- .../unstable-book/src/language-features/repr128.md | 18 -- .../clippy/tests/ui/auxiliary/proc_macro_attr.rs | 3 +- .../clippy/tests/ui/auxiliary/proc_macro_derive.rs | 3 +- src/tools/clippy/tests/ui/cast.rs | 2 - src/tools/clippy/tests/ui/cast.stderr | 184 ++++++++++----------- .../tests/ui/crashes/auxiliary/proc_macro_crash.rs | 3 - src/tools/tidy/src/issues.txt | 1 - tests/codegen/enum/enum-u128.rs | 3 - tests/debuginfo/msvc-pretty-enums.rs | 2 - tests/mir-opt/enum_opt.rs | 2 - tests/mir-opt/matches_reduce_branches.rs | 1 - tests/run-make/repr128-dwarf/main.rs | 2 - tests/rustdoc-json/enums/discriminant/limits.rs | 3 - tests/ui/enum-discriminant/discriminant_size.rs | 3 +- .../ui/enum-discriminant/discriminant_size.stderr | 11 -- tests/ui/enum-discriminant/issue-43398.rs | 14 -- tests/ui/enum-discriminant/issue-43398.stderr | 11 -- .../ui/enum-discriminant/issue-70509-partial_eq.rs | 2 - .../issue-70509-partial_eq.stderr | 11 -- .../repr128-get-discriminant-issue-43398.rs | 12 ++ tests/ui/enum-discriminant/repr128.rs | 3 +- tests/ui/enum-discriminant/repr128.stderr | 11 -- tests/ui/error-codes/E0658.rs | 5 +- tests/ui/error-codes/E0658.stderr | 11 +- tests/ui/feature-gates/feature-gate-repr128.rs | 6 - tests/ui/feature-gates/feature-gate-repr128.stderr | 13 -- tests/ui/lint/lint-ctypes-enum.rs | 2 - tests/ui/lint/lint-ctypes-enum.stderr | 68 ++++---- .../enums/repr/should_handle_all.rs | 3 +- 33 files changed, 155 insertions(+), 289 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/repr128.md delete mode 100644 tests/ui/enum-discriminant/discriminant_size.stderr delete mode 100644 tests/ui/enum-discriminant/issue-43398.rs delete mode 100644 tests/ui/enum-discriminant/issue-43398.stderr delete mode 100644 tests/ui/enum-discriminant/issue-70509-partial_eq.stderr create mode 100644 tests/ui/enum-discriminant/repr128-get-discriminant-issue-43398.rs delete mode 100644 tests/ui/enum-discriminant/repr128.stderr delete mode 100644 tests/ui/feature-gates/feature-gate-repr128.rs delete mode 100644 tests/ui/feature-gates/feature-gate-repr128.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0658.md b/compiler/rustc_error_codes/src/error_codes/E0658.md index 24245a38ae0..65c82e4fb6e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0658.md +++ b/compiler/rustc_error_codes/src/error_codes/E0658.md @@ -3,10 +3,7 @@ An unstable feature was used. Erroneous code example: ```compile_fail,E0658 -#[repr(u128)] // error: use of unstable library feature 'repr128' -enum Foo { - Bar(u64), -} +use std::intrinsics; // error: use of unstable library feature `core_intrinsics` ``` If you're using a stable or a beta version of rustc, you won't be able to use @@ -17,12 +14,9 @@ If you're using a nightly version of rustc, just add the corresponding feature to be able to use it: ``` -#![feature(repr128)] +#![feature(core_intrinsics)] -#[repr(u128)] // ok! -enum Foo { - Bar(u64), -} +use std::intrinsics; // ok! ``` [rustup]: https://rust-lang.github.io/rustup/concepts/channels.html diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 820af9ac84b..ffa6ffb40b6 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -360,6 +360,8 @@ declare_features! ( (accepted, relaxed_adts, "1.19.0", Some(35626)), /// Lessens the requirements for structs to implement `Unsize`. (accepted, relaxed_struct_unsize, "1.58.0", Some(81793)), + /// Allows the `#[repr(i128)]` attribute for enums. + (accepted, repr128, "CURRENT_RUSTC_VERSION", Some(56071)), /// Allows `repr(align(16))` struct attribute (RFC 1358). (accepted, repr_align, "1.25.0", Some(33626)), /// Allows using `#[repr(align(X))]` on enums with equivalent semantics diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3e408a03111..b46eac6d8a6 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -621,8 +621,6 @@ declare_features! ( (incomplete, ref_pat_eat_one_layer_2024_structural, "1.81.0", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), - /// Allows the `#[repr(i128)]` attribute for enums. - (incomplete, repr128, "1.16.0", Some(56071)), /// Allows `repr(simd)` and importing the various simd intrinsics. (unstable, repr_simd, "1.4.0", Some(27731)), /// Allows bounding the return type of AFIT/RPITIT. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index db7a5fe7897..846eacce9e1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -18,7 +18,7 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; -use rustc_middle::ty::util::{Discr, IntTypeExt}; +use rustc_middle::ty::util::Discr; use rustc_middle::ty::{ AdtDef, BottomUpFolder, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, fold_regions, @@ -1385,19 +1385,6 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { ); } - let repr_type_ty = def.repr().discr_type().to_ty(tcx); - if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { - if !tcx.features().repr128() { - feature_err( - &tcx.sess, - sym::repr128, - tcx.def_span(def_id), - "repr with 128-bit type is unstable", - ) - .emit(); - } - } - for v in def.variants() { if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr { tcx.ensure_ok().typeck(discr_def_id.expect_local()); diff --git a/src/doc/unstable-book/src/language-features/repr128.md b/src/doc/unstable-book/src/language-features/repr128.md deleted file mode 100644 index 146f50ee67b..00000000000 --- a/src/doc/unstable-book/src/language-features/repr128.md +++ /dev/null @@ -1,18 +0,0 @@ -# `repr128` - -The tracking issue for this feature is: [#56071] - -[#56071]: https://github.com/rust-lang/rust/issues/56071 - ------------------------- - -The `repr128` feature adds support for `#[repr(u128)]` on `enum`s. - -```rust -#![feature(repr128)] - -#[repr(u128)] -enum Foo { - Bar(u64), -} -``` diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs index 4c61c5accd3..9b8e62867f0 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs @@ -1,5 +1,4 @@ -#![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)] -#![allow(incomplete_features)] +#![feature(proc_macro_hygiene, proc_macro_quote, box_patterns)] #![allow(clippy::useless_conversion, clippy::uninlined_format_args)] extern crate proc_macro; diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs index 1815dd58f51..5992d15935d 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs @@ -1,5 +1,4 @@ -#![feature(repr128, proc_macro_quote, proc_macro_span)] -#![allow(incomplete_features)] +#![feature(proc_macro_quote, proc_macro_span)] #![allow(clippy::field_reassign_with_default)] #![allow(clippy::eq_op)] #![allow(clippy::literal_string_with_formatting_args)] diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs index 77329cf5455..525be821650 100644 --- a/src/tools/clippy/tests/ui/cast.rs +++ b/src/tools/clippy/tests/ui/cast.rs @@ -1,7 +1,5 @@ //@no-rustfix: only some diagnostics have suggestions -#![feature(repr128)] -#![allow(incomplete_features)] #![warn( clippy::cast_precision_loss, clippy::cast_possible_truncation, diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr index 4d03282f667..1cb30d95667 100644 --- a/src/tools/clippy/tests/ui/cast.stderr +++ b/src/tools/clippy/tests/ui/cast.stderr @@ -1,5 +1,5 @@ error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:25:5 + --> tests/ui/cast.rs:23:5 | LL | x0 as f32; | ^^^^^^^^^ @@ -8,37 +8,37 @@ LL | x0 as f32; = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]` error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:29:5 + --> tests/ui/cast.rs:27:5 | LL | x1 as f32; | ^^^^^^^^^ error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:32:5 + --> tests/ui/cast.rs:30:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:36:5 + --> tests/ui/cast.rs:34:5 | LL | x2 as f32; | ^^^^^^^^^ error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:40:5 + --> tests/ui/cast.rs:38:5 | LL | x3 as f32; | ^^^^^^^^^ error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:43:5 + --> tests/ui/cast.rs:41:5 | LL | x3 as f64; | ^^^^^^^^^ error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:47:5 + --> tests/ui/cast.rs:45:5 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | 1f32 as i32; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]` error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:50:5 + --> tests/ui/cast.rs:48:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | 1f32 as u32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:50:5 + --> tests/ui/cast.rs:48:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | 1f32 as u32; = help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]` error: casting `f64` to `f32` may truncate the value - --> tests/ui/cast.rs:54:5 + --> tests/ui/cast.rs:52:5 | LL | 1f64 as f32; | ^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | 1f64 as f32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:57:5 + --> tests/ui/cast.rs:55:5 | LL | 1i32 as i8; | ^^^^^^^^^^ @@ -86,7 +86,7 @@ LL + i8::try_from(1i32); | error: casting `i32` to `u8` may truncate the value - --> tests/ui/cast.rs:60:5 + --> tests/ui/cast.rs:58:5 | LL | 1i32 as u8; | ^^^^^^^^^^ @@ -99,7 +99,7 @@ LL + u8::try_from(1i32); | error: casting `f64` to `isize` may truncate the value - --> tests/ui/cast.rs:63:5 + --> tests/ui/cast.rs:61:5 | LL | 1f64 as isize; | ^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL | 1f64 as isize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may truncate the value - --> tests/ui/cast.rs:66:5 + --> tests/ui/cast.rs:64:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ @@ -115,13 +115,13 @@ LL | 1f64 as usize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:66:5 + --> tests/ui/cast.rs:64:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting `u32` to `u16` may truncate the value - --> tests/ui/cast.rs:70:5 + --> tests/ui/cast.rs:68:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL + u16::try_from(1f32 as u32); | error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:70:5 + --> tests/ui/cast.rs:68:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ @@ -142,13 +142,13 @@ LL | 1f32 as u32 as u16; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:70:5 + --> tests/ui/cast.rs:68:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:76:22 + --> tests/ui/cast.rs:74:22 | LL | let _x: i8 = 1i32 as _; | ^^^^^^^^^ @@ -161,7 +161,7 @@ LL + let _x: i8 = 1i32.try_into(); | error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:79:9 + --> tests/ui/cast.rs:77:9 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL | 1f32 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `i32` may truncate the value - --> tests/ui/cast.rs:82:9 + --> tests/ui/cast.rs:80:9 | LL | 1f64 as i32; | ^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | 1f64 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may truncate the value - --> tests/ui/cast.rs:85:9 + --> tests/ui/cast.rs:83:9 | LL | 1f32 as u8; | ^^^^^^^^^^ @@ -185,13 +185,13 @@ LL | 1f32 as u8; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:85:9 + --> tests/ui/cast.rs:83:9 | LL | 1f32 as u8; | ^^^^^^^^^^ error: casting `u8` to `i8` may wrap around the value - --> tests/ui/cast.rs:90:5 + --> tests/ui/cast.rs:88:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -200,31 +200,31 @@ LL | 1u8 as i8; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]` error: casting `u16` to `i16` may wrap around the value - --> tests/ui/cast.rs:93:5 + --> tests/ui/cast.rs:91:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting `u32` to `i32` may wrap around the value - --> tests/ui/cast.rs:96:5 + --> tests/ui/cast.rs:94:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting `u64` to `i64` may wrap around the value - --> tests/ui/cast.rs:99:5 + --> tests/ui/cast.rs:97:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting `usize` to `isize` may wrap around the value - --> tests/ui/cast.rs:102:5 + --> tests/ui/cast.rs:100:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting `usize` to `i8` may truncate the value - --> tests/ui/cast.rs:106:5 + --> tests/ui/cast.rs:104:5 | LL | 1usize as i8; | ^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + i8::try_from(1usize); | error: casting `usize` to `i16` may truncate the value - --> tests/ui/cast.rs:110:5 + --> tests/ui/cast.rs:108:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL + i16::try_from(1usize); | error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:110:5 + --> tests/ui/cast.rs:108:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -259,7 +259,7 @@ LL | 1usize as i16; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:115:5 + --> tests/ui/cast.rs:113:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -272,19 +272,19 @@ LL + i32::try_from(1usize); | error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:115:5 + --> tests/ui/cast.rs:113:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:120:5 + --> tests/ui/cast.rs:118:5 | LL | 1usize as i64; | ^^^^^^^^^^^^^ error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:126:5 + --> tests/ui/cast.rs:124:5 | LL | 1u16 as isize; | ^^^^^^^^^^^^^ @@ -293,13 +293,13 @@ LL | 1u16 as isize; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:130:5 + --> tests/ui/cast.rs:128:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:134:5 + --> tests/ui/cast.rs:132:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ @@ -312,55 +312,55 @@ LL + isize::try_from(1u64); | error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:134:5 + --> tests/ui/cast.rs:132:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:140:5 + --> tests/ui/cast.rs:138:5 | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:144:5 + --> tests/ui/cast.rs:142:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i8` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:156:5 + --> tests/ui/cast.rs:154:5 | LL | (i8::MIN).abs() as u8; | ^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:161:5 + --> tests/ui/cast.rs:159:5 | LL | (-1i64).abs() as u64; | ^^^^^^^^^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:163:5 + --> tests/ui/cast.rs:161:5 | LL | (-1isize).abs() as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:171:5 + --> tests/ui/cast.rs:169:5 | LL | (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:187:5 + --> tests/ui/cast.rs:185:5 | LL | (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> tests/ui/cast.rs:239:5 + --> tests/ui/cast.rs:237:5 | LL | (-99999999999i64).min(1) as i8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +373,7 @@ LL + i8::try_from((-99999999999i64).min(1)); | error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:253:5 + --> tests/ui/cast.rs:251:5 | LL | 999999u64.clamp(0, 256) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -386,7 +386,7 @@ LL + u8::try_from(999999u64.clamp(0, 256)); | error: casting `main::E2` to `u8` may truncate the value - --> tests/ui/cast.rs:276:21 + --> tests/ui/cast.rs:274:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -399,7 +399,7 @@ LL + let _ = u8::try_from(self); | error: casting `main::E2::B` to `u8` will truncate the value - --> tests/ui/cast.rs:279:21 + --> tests/ui/cast.rs:277:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -408,7 +408,7 @@ LL | let _ = Self::B as u8; = help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]` error: casting `main::E5` to `i8` may truncate the value - --> tests/ui/cast.rs:321:21 + --> tests/ui/cast.rs:319:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -421,13 +421,13 @@ LL + let _ = i8::try_from(self); | error: casting `main::E5::A` to `i8` will truncate the value - --> tests/ui/cast.rs:324:21 + --> tests/ui/cast.rs:322:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> tests/ui/cast.rs:342:21 + --> tests/ui/cast.rs:340:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -440,7 +440,7 @@ LL + let _ = i16::try_from(self); | error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:362:21 + --> tests/ui/cast.rs:360:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -453,7 +453,7 @@ LL + let _ = usize::try_from(self); | error: casting `main::E10` to `u16` may truncate the value - --> tests/ui/cast.rs:410:21 + --> tests/ui/cast.rs:408:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL + let _ = u16::try_from(self); | error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:422:13 + --> tests/ui/cast.rs:420:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -479,7 +479,7 @@ LL + let c = u8::try_from(q >> 16); | error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:427:13 + --> tests/ui/cast.rs:425:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ @@ -492,85 +492,85 @@ LL + let c = u8::try_from(q / 1000); | error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:440:9 + --> tests/ui/cast.rs:438:9 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:446:32 + --> tests/ui/cast.rs:444:32 | LL | let _a = |x: i32| -> u32 { (x * x * x * x) as u32 }; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:449:5 + --> tests/ui/cast.rs:447:5 | LL | (2_i32).checked_pow(3).unwrap() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:451:5 + --> tests/ui/cast.rs:449:5 | LL | (-2_i32).pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:456:5 + --> tests/ui/cast.rs:454:5 | LL | (-5_i32 % 2) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:459:5 + --> tests/ui/cast.rs:457:5 | LL | (-5_i32 % -2) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:463:5 + --> tests/ui/cast.rs:461:5 | LL | (-2_i32 >> 1) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:467:5 + --> tests/ui/cast.rs:465:5 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:469:5 + --> tests/ui/cast.rs:467:5 | LL | (x * x * x) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:473:5 + --> tests/ui/cast.rs:471:5 | LL | (y * y * y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:476:5 + --> tests/ui/cast.rs:474:5 | LL | (y * y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:478:5 + --> tests/ui/cast.rs:476:5 | LL | (y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:481:5 + --> tests/ui/cast.rs:479:5 | LL | (y / y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `/` - --> tests/ui/cast.rs:481:6 + --> tests/ui/cast.rs:479:6 | LL | (y / y * y * -2) as u16; | ^^^^^ @@ -578,97 +578,97 @@ LL | (y / y * y * -2) as u16; = note: `#[deny(clippy::eq_op)]` on by default error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:485:5 + --> tests/ui/cast.rs:483:5 | LL | (y + y + y + -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:488:5 + --> tests/ui/cast.rs:486:5 | LL | (y + y + y + 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:492:5 + --> tests/ui/cast.rs:490:5 | LL | (z + -2) as u16; | ^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:495:5 + --> tests/ui/cast.rs:493:5 | LL | (z + z + 2) as u16; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:499:9 + --> tests/ui/cast.rs:497:9 | LL | (a * a * b * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:501:9 + --> tests/ui/cast.rs:499:9 | LL | (a * b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:504:9 + --> tests/ui/cast.rs:502:9 | LL | (a * -b * c) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:507:9 + --> tests/ui/cast.rs:505:9 | LL | (a * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:509:9 + --> tests/ui/cast.rs:507:9 | LL | (a * -2) as u32; | ^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:512:9 + --> tests/ui/cast.rs:510:9 | LL | (a * b * c * -2) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:515:9 + --> tests/ui/cast.rs:513:9 | LL | (a / b) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:517:9 + --> tests/ui/cast.rs:515:9 | LL | (a / b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:520:9 + --> tests/ui/cast.rs:518:9 | LL | (a / b + b * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:523:9 + --> tests/ui/cast.rs:521:9 | LL | a.saturating_pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:526:9 + --> tests/ui/cast.rs:524:9 | LL | (a.abs() * b.pow(2) / c.abs()) as u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:534:21 + --> tests/ui/cast.rs:532:21 | LL | let _ = i32::MIN as u32; // cast_sign_loss | ^^^^^^^^^^^^^^^ @@ -679,7 +679,7 @@ LL | m!(); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:537:21 + --> tests/ui/cast.rs:535:21 | LL | let _ = u32::MAX as u8; // cast_possible_truncation | ^^^^^^^^^^^^^^ @@ -696,7 +696,7 @@ LL + let _ = u8::try_from(u32::MAX); // cast_possible_truncation | error: casting `f64` to `f32` may truncate the value - --> tests/ui/cast.rs:540:21 + --> tests/ui/cast.rs:538:21 | LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -708,7 +708,7 @@ LL | m!(); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:551:5 + --> tests/ui/cast.rs:549:5 | LL | bar.unwrap().unwrap() as usize | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -721,13 +721,13 @@ LL + usize::try_from(bar.unwrap().unwrap()) | error: casting `i64` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:551:5 + --> tests/ui/cast.rs:549:5 | LL | bar.unwrap().unwrap() as usize | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:568:5 + --> tests/ui/cast.rs:566:5 | LL | (256 & 999999u64) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -740,7 +740,7 @@ LL + u8::try_from(256 & 999999u64); | error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:571:5 + --> tests/ui/cast.rs:569:5 | LL | (255 % 999999u64) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs index 5dffddc119a..cf37a4c5c4b 100644 --- a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs +++ b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs @@ -1,6 +1,3 @@ -#![feature(repr128)] -#![allow(incomplete_features)] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 1d0ddd56eec..3e9d79224fd 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -939,7 +939,6 @@ ui/enum-discriminant/auxiliary/issue-41394.rs ui/enum-discriminant/issue-104519.rs ui/enum-discriminant/issue-41394-rpass.rs ui/enum-discriminant/issue-41394.rs -ui/enum-discriminant/issue-43398.rs ui/enum-discriminant/issue-46519.rs ui/enum-discriminant/issue-50689.rs ui/enum-discriminant/issue-51582.rs diff --git a/tests/codegen/enum/enum-u128.rs b/tests/codegen/enum/enum-u128.rs index ecdff3c5ce3..2676669f3e3 100644 --- a/tests/codegen/enum/enum-u128.rs +++ b/tests/codegen/enum/enum-u128.rs @@ -13,9 +13,6 @@ // CHECK: {{.*}}DIEnumerator{{.*}}name: "Hi",{{.*}}value: 18446744073709551616,{{.*}} // CHECK: {{.*}}DIEnumerator{{.*}}name: "Bar",{{.*}}value: 18446745000000000123,{{.*}} -#![allow(incomplete_features)] -#![feature(repr128)] - #[repr(u128)] pub enum Foo { Lo, diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs index 06bc25dc5d5..aa6629ef1e1 100644 --- a/tests/debuginfo/msvc-pretty-enums.rs +++ b/tests/debuginfo/msvc-pretty-enums.rs @@ -231,8 +231,6 @@ // cdb-command: dx c_style_i128_d // cdb-check: c_style_i128_d : D [Type: enum2$] #![feature(rustc_attrs)] -#![feature(repr128)] -#![feature(arbitrary_enum_discriminant)] use std::num::NonZero; diff --git a/tests/mir-opt/enum_opt.rs b/tests/mir-opt/enum_opt.rs index e42be8ac06d..81390567c2b 100644 --- a/tests/mir-opt/enum_opt.rs +++ b/tests/mir-opt/enum_opt.rs @@ -3,8 +3,6 @@ // EMIT_MIR_FOR_EACH_BIT_WIDTH //@ compile-flags: -Zunsound-mir-opts -Zdump-mir-exclude-alloc-bytes -#![feature(arbitrary_enum_discriminant, repr128)] - // Tests that an enum with a variant with no data gets correctly transformed. pub enum NoData { Large([u8; 8196]), diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index 3372ae2f2a6..00131b0116d 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -1,6 +1,5 @@ //@ test-mir-pass: MatchBranchSimplification -#![feature(repr128)] #![feature(core_intrinsics)] #![feature(custom_mir)] #![allow(non_camel_case_types)] diff --git a/tests/run-make/repr128-dwarf/main.rs b/tests/run-make/repr128-dwarf/main.rs index 9842ab4a342..a8a414fd72e 100644 --- a/tests/run-make/repr128-dwarf/main.rs +++ b/tests/run-make/repr128-dwarf/main.rs @@ -1,5 +1,3 @@ -#![feature(repr128)] - // Use .to_le() to ensure that the bytes are in the same order on both little- and big-endian // platforms. diff --git a/tests/rustdoc-json/enums/discriminant/limits.rs b/tests/rustdoc-json/enums/discriminant/limits.rs index c84181334e3..e98271b7c80 100644 --- a/tests/rustdoc-json/enums/discriminant/limits.rs +++ b/tests/rustdoc-json/enums/discriminant/limits.rs @@ -1,6 +1,3 @@ -#![feature(repr128)] -#![allow(incomplete_features)] - #[repr(u64)] pub enum U64 { //@ is "$.index[?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"' diff --git a/tests/ui/enum-discriminant/discriminant_size.rs b/tests/ui/enum-discriminant/discriminant_size.rs index a3ec1b28e5c..b1feff3c59e 100644 --- a/tests/ui/enum-discriminant/discriminant_size.rs +++ b/tests/ui/enum-discriminant/discriminant_size.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(core_intrinsics, repr128)] -//~^ WARN the feature `repr128` is incomplete +#![feature(core_intrinsics)] use std::intrinsics::discriminant_value; diff --git a/tests/ui/enum-discriminant/discriminant_size.stderr b/tests/ui/enum-discriminant/discriminant_size.stderr deleted file mode 100644 index 9b1505b5c46..00000000000 --- a/tests/ui/enum-discriminant/discriminant_size.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/discriminant_size.rs:2:29 - | -LL | #![feature(core_intrinsics, repr128)] - | ^^^^^^^ - | - = note: see issue #56071 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/enum-discriminant/issue-43398.rs b/tests/ui/enum-discriminant/issue-43398.rs deleted file mode 100644 index 574a4b3ad5a..00000000000 --- a/tests/ui/enum-discriminant/issue-43398.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass - -#![feature(core_intrinsics)] -#![feature(repr128)] -//~^ WARN the feature `repr128` is incomplete - -#[repr(i128)] -enum Big { A, B } - -fn main() { - println!("{} {:?}", - std::intrinsics::discriminant_value(&Big::A), - std::mem::discriminant(&Big::B)); -} diff --git a/tests/ui/enum-discriminant/issue-43398.stderr b/tests/ui/enum-discriminant/issue-43398.stderr deleted file mode 100644 index fc7bbd06284..00000000000 --- a/tests/ui/enum-discriminant/issue-43398.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-43398.rs:4:12 - | -LL | #![feature(repr128)] - | ^^^^^^^ - | - = note: see issue #56071 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/enum-discriminant/issue-70509-partial_eq.rs b/tests/ui/enum-discriminant/issue-70509-partial_eq.rs index e98532c1207..5e71972c280 100644 --- a/tests/ui/enum-discriminant/issue-70509-partial_eq.rs +++ b/tests/ui/enum-discriminant/issue-70509-partial_eq.rs @@ -1,6 +1,4 @@ //@ run-pass -#![feature(repr128)] -//~^ WARN the feature `repr128` is incomplete #[derive(PartialEq, Debug)] #[repr(i128)] diff --git a/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr b/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr deleted file mode 100644 index 2eef930c394..00000000000 --- a/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-70509-partial_eq.rs:2:12 - | -LL | #![feature(repr128)] - | ^^^^^^^ - | - = note: see issue #56071 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/enum-discriminant/repr128-get-discriminant-issue-43398.rs b/tests/ui/enum-discriminant/repr128-get-discriminant-issue-43398.rs new file mode 100644 index 00000000000..2bb9725fb77 --- /dev/null +++ b/tests/ui/enum-discriminant/repr128-get-discriminant-issue-43398.rs @@ -0,0 +1,12 @@ +//@ run-pass + +#![feature(core_intrinsics)] + +#[repr(i128)] +enum Big { A, B } + +fn main() { + println!("{} {:?}", + std::intrinsics::discriminant_value(&Big::A), + std::mem::discriminant(&Big::B)); +} diff --git a/tests/ui/enum-discriminant/repr128.rs b/tests/ui/enum-discriminant/repr128.rs index 075ff7a7676..d59a5b3e256 100644 --- a/tests/ui/enum-discriminant/repr128.rs +++ b/tests/ui/enum-discriminant/repr128.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(repr128, core_intrinsics, discriminant_kind)] -//~^ WARN the feature `repr128` is incomplete +#![feature(core_intrinsics, discriminant_kind)] use std::intrinsics::discriminant_value; use std::marker::DiscriminantKind; diff --git a/tests/ui/enum-discriminant/repr128.stderr b/tests/ui/enum-discriminant/repr128.stderr deleted file mode 100644 index da8d75c11af..00000000000 --- a/tests/ui/enum-discriminant/repr128.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/repr128.rs:2:12 - | -LL | #![feature(repr128, core_intrinsics, discriminant_kind)] - | ^^^^^^^ - | - = note: see issue #56071 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/error-codes/E0658.rs b/tests/ui/error-codes/E0658.rs index 9c9b95d70a7..e51674cdf92 100644 --- a/tests/ui/error-codes/E0658.rs +++ b/tests/ui/error-codes/E0658.rs @@ -1,6 +1,3 @@ -#[repr(u128)] -enum Foo { //~ ERROR E0658 - Bar(u64), -} +use std::intrinsics; //~ ERROR E0658 fn main() {} diff --git a/tests/ui/error-codes/E0658.stderr b/tests/ui/error-codes/E0658.stderr index e1e812940ec..ae7ecbbc5cb 100644 --- a/tests/ui/error-codes/E0658.stderr +++ b/tests/ui/error-codes/E0658.stderr @@ -1,11 +1,10 @@ -error[E0658]: repr with 128-bit type is unstable - --> $DIR/E0658.rs:2:1 +error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library + --> $DIR/E0658.rs:1:5 | -LL | enum Foo { - | ^^^^^^^^ +LL | use std::intrinsics; + | ^^^^^^^^^^^^^^^ | - = note: see issue #56071 for more information - = help: add `#![feature(repr128)]` to the crate attributes to enable + = help: add `#![feature(core_intrinsics)]` 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/feature-gates/feature-gate-repr128.rs b/tests/ui/feature-gates/feature-gate-repr128.rs deleted file mode 100644 index 0290874dd27..00000000000 --- a/tests/ui/feature-gates/feature-gate-repr128.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[repr(u128)] -enum A { //~ ERROR repr with 128-bit type is unstable - A(u64) -} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-repr128.stderr b/tests/ui/feature-gates/feature-gate-repr128.stderr deleted file mode 100644 index 2607032447b..00000000000 --- a/tests/ui/feature-gates/feature-gate-repr128.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: repr with 128-bit type is unstable - --> $DIR/feature-gate-repr128.rs:2:1 - | -LL | enum A { - | ^^^^^^ - | - = note: see issue #56071 for more information - = help: add `#![feature(repr128)]` 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 - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs index b2ef27b833b..612da86c956 100644 --- a/tests/ui/lint/lint-ctypes-enum.rs +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -2,8 +2,6 @@ #![deny(improper_ctypes)] #![feature(ptr_internals)] #![feature(transparent_unions)] -#![feature(repr128)] -#![allow(incomplete_features)] use std::num; diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index d5fc844f756..50a6f526f26 100644 --- a/tests/ui/lint/lint-ctypes-enum.stderr +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `U`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:84:14 + --> $DIR/lint-ctypes-enum.rs:82:14 | LL | fn uf(x: U); | ^ not FFI-safe @@ -7,7 +7,7 @@ LL | fn uf(x: U); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:11:1 + --> $DIR/lint-ctypes-enum.rs:9:1 | LL | enum U { | ^^^^^^ @@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ error: `extern` block uses type `B`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:85:14 + --> $DIR/lint-ctypes-enum.rs:83:14 | LL | fn bf(x: B); | ^ not FFI-safe @@ -26,13 +26,13 @@ LL | fn bf(x: B); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:14:1 + --> $DIR/lint-ctypes-enum.rs:12:1 | LL | enum B { | ^^^^^^ error: `extern` block uses type `T`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:86:14 + --> $DIR/lint-ctypes-enum.rs:84:14 | LL | fn tf(x: T); | ^ not FFI-safe @@ -40,39 +40,39 @@ LL | fn tf(x: T); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:18:1 + --> $DIR/lint-ctypes-enum.rs:16:1 | LL | enum T { | ^^^^^^ error: `extern` block uses type `U128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:90:21 + --> $DIR/lint-ctypes-enum.rs:88:21 | LL | fn repr_u128(x: U128); | ^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:46:1 + --> $DIR/lint-ctypes-enum.rs:44:1 | LL | enum U128 { | ^^^^^^^^^ error: `extern` block uses type `I128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:91:21 + --> $DIR/lint-ctypes-enum.rs:89:21 | LL | fn repr_i128(x: I128); | ^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:53:1 + --> $DIR/lint-ctypes-enum.rs:51:1 | LL | enum I128 { | ^^^^^^^^^ error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:100:31 + --> $DIR/lint-ctypes-enum.rs:98:31 | LL | fn option_nonzero_u128(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -80,7 +80,7 @@ LL | fn option_nonzero_u128(x: Option>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:107:31 + --> $DIR/lint-ctypes-enum.rs:105:31 | LL | fn option_nonzero_i128(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -88,7 +88,7 @@ LL | fn option_nonzero_i128(x: Option>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Option>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:112:36 + --> $DIR/lint-ctypes-enum.rs:110:36 | LL | fn option_transparent_union(x: Option>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -97,7 +97,7 @@ LL | fn option_transparent_union(x: Option = note: enum has no representation hint error: `extern` block uses type `Option>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:114:28 + --> $DIR/lint-ctypes-enum.rs:112:28 | LL | fn option_repr_rust(x: Option>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -106,7 +106,7 @@ LL | fn option_repr_rust(x: Option>>); = note: enum has no representation hint error: `extern` block uses type `Option`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:115:21 + --> $DIR/lint-ctypes-enum.rs:113:21 | LL | fn option_u8(x: Option); | ^^^^^^^^^^ not FFI-safe @@ -115,7 +115,7 @@ LL | fn option_u8(x: Option); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:125:33 + --> $DIR/lint-ctypes-enum.rs:123:33 | LL | fn result_nonzero_u128_t(x: Result, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -123,7 +123,7 @@ LL | fn result_nonzero_u128_t(x: Result, ()>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:132:33 + --> $DIR/lint-ctypes-enum.rs:130:33 | LL | fn result_nonzero_i128_t(x: Result, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -131,7 +131,7 @@ LL | fn result_nonzero_i128_t(x: Result, ()>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:137:38 + --> $DIR/lint-ctypes-enum.rs:135:38 | LL | fn result_transparent_union_t(x: Result>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -140,7 +140,7 @@ LL | fn result_transparent_union_t(x: Result>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:139:30 + --> $DIR/lint-ctypes-enum.rs:137:30 | LL | fn result_repr_rust_t(x: Result>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -149,7 +149,7 @@ LL | fn result_repr_rust_t(x: Result>, ()>); = note: enum has no representation hint error: `extern` block uses type `Result, U>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:143:51 + --> $DIR/lint-ctypes-enum.rs:141:51 | LL | fn result_1zst_exhaustive_single_variant_t(x: Result, U>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -158,7 +158,7 @@ LL | fn result_1zst_exhaustive_single_variant_t(x: Result, = note: enum has no representation hint error: `extern` block uses type `Result, B>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:145:53 + --> $DIR/lint-ctypes-enum.rs:143:53 | LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result, B>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -167,7 +167,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result = note: enum has no representation hint error: `extern` block uses type `Result, NonExhaustive>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:147:51 + --> $DIR/lint-ctypes-enum.rs:145:51 | LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, NonExhaustive>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -176,7 +176,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, = note: enum has no representation hint error: `extern` block uses type `Result, Field>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:150:49 + --> $DIR/lint-ctypes-enum.rs:148:49 | LL | fn result_1zst_exhaustive_single_field_t(x: Result, Field>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -185,7 +185,7 @@ LL | fn result_1zst_exhaustive_single_field_t(x: Result, Fi = note: enum has no representation hint error: `extern` block uses type `Result>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:152:30 + --> $DIR/lint-ctypes-enum.rs:150:30 | LL | fn result_cascading_t(x: Result>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -194,7 +194,7 @@ LL | fn result_cascading_t(x: Result>, ()>); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:163:33 + --> $DIR/lint-ctypes-enum.rs:161:33 | LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -202,7 +202,7 @@ LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:170:33 + --> $DIR/lint-ctypes-enum.rs:168:33 | LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -210,7 +210,7 @@ LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result<(), TransparentUnion>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:175:38 + --> $DIR/lint-ctypes-enum.rs:173:38 | LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -219,7 +219,7 @@ LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:177:30 + --> $DIR/lint-ctypes-enum.rs:175:30 | LL | fn result_repr_rust_e(x: Result<(), Rust>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -228,7 +228,7 @@ LL | fn result_repr_rust_e(x: Result<(), Rust>>); = note: enum has no representation hint error: `extern` block uses type `Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:181:51 + --> $DIR/lint-ctypes-enum.rs:179:51 | LL | fn result_1zst_exhaustive_single_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -237,7 +237,7 @@ LL | fn result_1zst_exhaustive_single_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:183:53 + --> $DIR/lint-ctypes-enum.rs:181:53 | LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -246,7 +246,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:185:51 + --> $DIR/lint-ctypes-enum.rs:183:51 | LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -255,7 +255,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:188:49 + --> $DIR/lint-ctypes-enum.rs:186:49 | LL | fn result_1zst_exhaustive_single_field_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -264,7 +264,7 @@ LL | fn result_1zst_exhaustive_single_field_e(x: Result>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:190:30 + --> $DIR/lint-ctypes-enum.rs:188:30 | LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -273,7 +273,7 @@ LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); = note: enum has no representation hint error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:192:27 + --> $DIR/lint-ctypes-enum.rs:190:27 | LL | fn result_unit_t_e(x: Result<(), ()>); | ^^^^^^^^^^^^^^ not FFI-safe diff --git a/tests/ui/transmutability/enums/repr/should_handle_all.rs b/tests/ui/transmutability/enums/repr/should_handle_all.rs index dec0126f22d..192b7cdcf72 100644 --- a/tests/ui/transmutability/enums/repr/should_handle_all.rs +++ b/tests/ui/transmutability/enums/repr/should_handle_all.rs @@ -1,8 +1,7 @@ //@ check-pass #![crate_type = "lib"] -#![feature(repr128)] #![feature(transmutability)] -#![allow(dead_code, incomplete_features, non_camel_case_types)] +#![allow(dead_code, non_camel_case_types)] mod assert { use std::mem::{Assume, TransmuteFrom}; -- cgit 1.4.1-3-g733a5 From 8237107d88866d4f4525f77384c653d4c80ad4df Mon Sep 17 00:00:00 2001 From: Patrick-6 Date: Wed, 28 May 2025 17:05:45 +0200 Subject: Add comments to diagnostic items --- library/std/src/sys/sync/mutex/futex.rs | 3 +++ library/std/src/sys/sync/mutex/pthread.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/library/std/src/sys/sync/mutex/futex.rs b/library/std/src/sys/sync/mutex/futex.rs index 01e91a6294a..70e2ea9f605 100644 --- a/library/std/src/sys/sync/mutex/futex.rs +++ b/library/std/src/sys/sync/mutex/futex.rs @@ -19,12 +19,14 @@ impl Mutex { } #[inline] + // Make this a diagnostic item for Miri's concurrency model checker. #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")] pub fn try_lock(&self) -> bool { self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok() } #[inline] + // Make this a diagnostic item for Miri's concurrency model checker. #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")] pub fn lock(&self) { if self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_err() { @@ -82,6 +84,7 @@ impl Mutex { } #[inline] + // Make this a diagnostic item for Miri's concurrency model checker. #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")] pub unsafe fn unlock(&self) { if self.futex.swap(UNLOCKED, Release) == CONTENDED { diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs index 1d442248374..a7a3b47d0ec 100644 --- a/library/std/src/sys/sync/mutex/pthread.rs +++ b/library/std/src/sys/sync/mutex/pthread.rs @@ -28,6 +28,7 @@ impl Mutex { } #[inline] + // Make this a diagnostic item for Miri's concurrency model checker. #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")] pub fn lock(&self) { // SAFETY: we call `init` above, therefore reentrant locking is safe. @@ -36,6 +37,7 @@ impl Mutex { } #[inline] + // Make this a diagnostic item for Miri's concurrency model checker. #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")] pub unsafe fn unlock(&self) { // SAFETY: the mutex can only be locked if it is already initialized @@ -44,6 +46,7 @@ impl Mutex { } #[inline] + // Make this a diagnostic item for Miri's concurrency model checker. #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")] pub fn try_lock(&self) -> bool { // SAFETY: we call `init` above, therefore reentrant locking is safe. -- cgit 1.4.1-3-g733a5 From 9f2ee0f4fb1420f9b49faadaed6cd021135ff354 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 28 May 2025 11:30:18 -0700 Subject: Add eholk to compiler reviewer rotation Now that we have work queue limits on triagebot, I'm happy to share some of the review load. --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 12cbc926a4a..b74159e5e5f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1196,6 +1196,7 @@ compiler = [ "@BoxyUwU", "@compiler-errors", "@davidtwco", + "@eholk", "@fee1-dead", "@fmease", "@jieyouxu", -- cgit 1.4.1-3-g733a5 From c9addbe0e5ed754ed356fa1422db6fdfcc87a6f6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 May 2025 11:51:21 +0200 Subject: 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 a319ca41cf9..6b5ec06c136 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -04a67d5a0587ed98632f82c404ae20f9f0a51a1d +38081f22c2d7380f272aa1d7fa9b935637701c2d -- cgit 1.4.1-3-g733a5 From afc64242b61041ee2f6e107c9483957dacfbf090 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Sat, 31 May 2025 00:30:37 +0500 Subject: cleaned up some tests --- tests/ui/auto-ref-slice-plus-ref.rs | 27 ---------- tests/ui/auto-ref-slice-plus-ref.stderr | 57 ---------------------- tests/ui/autoderef-full-lval.rs | 25 ---------- tests/ui/autoderef-full-lval.stderr | 31 ------------ tests/ui/autoref-autoderef/autoderef-box-no-add.rs | 35 +++++++++++++ .../autoref-autoderef/autoderef-box-no-add.stderr | 31 ++++++++++++ tests/ui/bare-fn-implements-fn-mut.rs | 25 ---------- tests/ui/bare-static-string.rs | 6 --- tests/ui/big-literals.rs | 17 ------- .../bare-fn-implements-fn-mut.rs | 29 +++++++++++ tests/ui/lint/overflowing-literals-valid.rs | 19 ++++++++ tests/ui/methods/vec-autoderef-autoref.rs | 26 ++++++++++ tests/ui/methods/vec-autoderef-autoref.stderr | 57 ++++++++++++++++++++++ tests/ui/str/str-static-literal.rs | 8 +++ 14 files changed, 205 insertions(+), 188 deletions(-) delete mode 100644 tests/ui/auto-ref-slice-plus-ref.rs delete mode 100644 tests/ui/auto-ref-slice-plus-ref.stderr delete mode 100644 tests/ui/autoderef-full-lval.rs delete mode 100644 tests/ui/autoderef-full-lval.stderr create mode 100644 tests/ui/autoref-autoderef/autoderef-box-no-add.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-box-no-add.stderr delete mode 100644 tests/ui/bare-fn-implements-fn-mut.rs delete mode 100644 tests/ui/bare-static-string.rs delete mode 100644 tests/ui/big-literals.rs create mode 100644 tests/ui/functions-closures/bare-fn-implements-fn-mut.rs create mode 100644 tests/ui/lint/overflowing-literals-valid.rs create mode 100644 tests/ui/methods/vec-autoderef-autoref.rs create mode 100644 tests/ui/methods/vec-autoderef-autoref.stderr create mode 100644 tests/ui/str/str-static-literal.rs diff --git a/tests/ui/auto-ref-slice-plus-ref.rs b/tests/ui/auto-ref-slice-plus-ref.rs deleted file mode 100644 index 00b279d3226..00000000000 --- a/tests/ui/auto-ref-slice-plus-ref.rs +++ /dev/null @@ -1,27 +0,0 @@ -fn main() { - - // Testing that method lookup does not automatically borrow - // vectors to slices then automatically create a self reference. - - let mut a = vec![0]; - a.test_mut(); //~ ERROR no method named `test_mut` found - a.test(); //~ ERROR no method named `test` found - - ([1]).test(); //~ ERROR no method named `test` found - (&[1]).test(); //~ ERROR no method named `test` found -} - -trait MyIter { - fn test_mut(&mut self); - fn test(&self); -} - -impl<'a> MyIter for &'a [isize] { - fn test_mut(&mut self) { } - fn test(&self) { } -} - -impl<'a> MyIter for &'a str { - fn test_mut(&mut self) { } - fn test(&self) { } -} diff --git a/tests/ui/auto-ref-slice-plus-ref.stderr b/tests/ui/auto-ref-slice-plus-ref.stderr deleted file mode 100644 index 806c1ee064f..00000000000 --- a/tests/ui/auto-ref-slice-plus-ref.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in the current scope - --> $DIR/auto-ref-slice-plus-ref.rs:7:7 - | -LL | a.test_mut(); - | ^^^^^^^^ - | - = help: items from traits can only be used if the trait is implemented and in scope -note: `MyIter` defines an item `test_mut`, perhaps you need to implement it - --> $DIR/auto-ref-slice-plus-ref.rs:14:1 - | -LL | trait MyIter { - | ^^^^^^^^^^^^ -help: there is a method `get_mut` with a similar name, but with different arguments - --> $SRC_DIR/core/src/slice/mod.rs:LL:COL - -error[E0599]: no method named `test` found for struct `Vec<{integer}>` in the current scope - --> $DIR/auto-ref-slice-plus-ref.rs:8:7 - | -LL | a.test(); - | ^^^^ method not found in `Vec<{integer}>` - | - = help: items from traits can only be used if the trait is implemented and in scope -note: `MyIter` defines an item `test`, perhaps you need to implement it - --> $DIR/auto-ref-slice-plus-ref.rs:14:1 - | -LL | trait MyIter { - | ^^^^^^^^^^^^ - -error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope - --> $DIR/auto-ref-slice-plus-ref.rs:10:11 - | -LL | ([1]).test(); - | ^^^^ method not found in `[{integer}; 1]` - | - = help: items from traits can only be used if the trait is implemented and in scope -note: `MyIter` defines an item `test`, perhaps you need to implement it - --> $DIR/auto-ref-slice-plus-ref.rs:14:1 - | -LL | trait MyIter { - | ^^^^^^^^^^^^ - -error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope - --> $DIR/auto-ref-slice-plus-ref.rs:11:12 - | -LL | (&[1]).test(); - | ^^^^ method not found in `&[{integer}; 1]` - | - = help: items from traits can only be used if the trait is implemented and in scope -note: `MyIter` defines an item `test`, perhaps you need to implement it - --> $DIR/auto-ref-slice-plus-ref.rs:14:1 - | -LL | trait MyIter { - | ^^^^^^^^^^^^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/autoderef-full-lval.rs b/tests/ui/autoderef-full-lval.rs deleted file mode 100644 index 0fadc5c9827..00000000000 --- a/tests/ui/autoderef-full-lval.rs +++ /dev/null @@ -1,25 +0,0 @@ -struct Clam { - x: Box, - y: Box, -} - - - -struct Fish { - a: Box, -} - -fn main() { - let a: Clam = Clam{ x: Box::new(1), y: Box::new(2) }; - let b: Clam = Clam{ x: Box::new(10), y: Box::new(20) }; - let z: isize = a.x + b.y; - //~^ ERROR cannot add `Box` to `Box` - println!("{}", z); - assert_eq!(z, 21); - let forty: Fish = Fish{ a: Box::new(40) }; - let two: Fish = Fish{ a: Box::new(2) }; - let answer: isize = forty.a + two.a; - //~^ ERROR cannot add `Box` to `Box` - println!("{}", answer); - assert_eq!(answer, 42); -} diff --git a/tests/ui/autoderef-full-lval.stderr b/tests/ui/autoderef-full-lval.stderr deleted file mode 100644 index d90238a7fb2..00000000000 --- a/tests/ui/autoderef-full-lval.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0369]: cannot add `Box` to `Box` - --> $DIR/autoderef-full-lval.rs:15:24 - | -LL | let z: isize = a.x + b.y; - | --- ^ --- Box - | | - | Box - | -note: the foreign item type `Box` doesn't implement `Add` - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL - ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL - | - = note: not implement `Add` - -error[E0369]: cannot add `Box` to `Box` - --> $DIR/autoderef-full-lval.rs:21:33 - | -LL | let answer: isize = forty.a + two.a; - | ------- ^ ----- Box - | | - | Box - | -note: the foreign item type `Box` doesn't implement `Add` - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL - ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL - | - = note: not implement `Add` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/autoref-autoderef/autoderef-box-no-add.rs b/tests/ui/autoref-autoderef/autoderef-box-no-add.rs new file mode 100644 index 00000000000..f8085c1ae96 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-box-no-add.rs @@ -0,0 +1,35 @@ +//! Tests that auto-dereferencing does not allow addition of `Box` values. +//! +//! This test ensures that `Box` fields in structs (`Clam` and `Fish`) are not +//! automatically dereferenced to `isize` during addition operations, as `Box` +//! does not implement the `Add` trait. + +struct Clam { + x: Box, + y: Box, +} + +struct Fish { + a: Box, +} + +fn main() { + let a: Clam = Clam { + x: Box::new(1), + y: Box::new(2), + }; + let b: Clam = Clam { + x: Box::new(10), + y: Box::new(20), + }; + let z: isize = a.x + b.y; + //~^ ERROR cannot add `Box` to `Box` + println!("{}", z); + assert_eq!(z, 21); + let forty: Fish = Fish { a: Box::new(40) }; + let two: Fish = Fish { a: Box::new(2) }; + let answer: isize = forty.a + two.a; + //~^ ERROR cannot add `Box` to `Box` + println!("{}", answer); + assert_eq!(answer, 42); +} diff --git a/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr b/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr new file mode 100644 index 00000000000..20ef3352831 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr @@ -0,0 +1,31 @@ +error[E0369]: cannot add `Box` to `Box` + --> $DIR/autoderef-box-no-add.rs:25:24 + | +LL | let z: isize = a.x + b.y; + | --- ^ --- Box + | | + | Box + | +note: the foreign item type `Box` doesn't implement `Add` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL + | + = note: not implement `Add` + +error[E0369]: cannot add `Box` to `Box` + --> $DIR/autoderef-box-no-add.rs:31:33 + | +LL | let answer: isize = forty.a + two.a; + | ------- ^ ----- Box + | | + | Box + | +note: the foreign item type `Box` doesn't implement `Add` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL + | + = note: not implement `Add` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/bare-fn-implements-fn-mut.rs b/tests/ui/bare-fn-implements-fn-mut.rs deleted file mode 100644 index 49b31f28f8a..00000000000 --- a/tests/ui/bare-fn-implements-fn-mut.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ run-pass - -fn call_f(mut f: F) { - f(); -} - -fn f() { - println!("hello"); -} - -fn call_g String>(mut g: G, x: String, y: String) - -> String { - g(x, y) -} - -fn g(mut x: String, y: String) -> String { - x.push_str(&y); - x -} - -fn main() { - call_f(f); - assert_eq!(call_g(g, "foo".to_string(), "bar".to_string()), - "foobar"); -} diff --git a/tests/ui/bare-static-string.rs b/tests/ui/bare-static-string.rs deleted file mode 100644 index b71cf38cfe8..00000000000 --- a/tests/ui/bare-static-string.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass - -pub fn main() { - let x: &'static str = "foo"; - println!("{}", x); -} diff --git a/tests/ui/big-literals.rs b/tests/ui/big-literals.rs deleted file mode 100644 index d2f447a595c..00000000000 --- a/tests/ui/big-literals.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ run-pass -// Catch mistakes in the overflowing literals lint. -#![deny(overflowing_literals)] - -pub fn main() { - assert_eq!(0xffffffff, (!0 as u32)); - assert_eq!(4294967295, (!0 as u32)); - assert_eq!(0xffffffffffffffff, (!0 as u64)); - assert_eq!(18446744073709551615, (!0 as u64)); - - assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647); - - assert_eq!(-3.40282356e+38_f32, f32::MIN); - assert_eq!(3.40282356e+38_f32, f32::MAX); - assert_eq!(-1.7976931348623158e+308_f64, f64::MIN); - assert_eq!(1.7976931348623158e+308_f64, f64::MAX); -} diff --git a/tests/ui/functions-closures/bare-fn-implements-fn-mut.rs b/tests/ui/functions-closures/bare-fn-implements-fn-mut.rs new file mode 100644 index 00000000000..52d5ad3d0f7 --- /dev/null +++ b/tests/ui/functions-closures/bare-fn-implements-fn-mut.rs @@ -0,0 +1,29 @@ +//! Tests that bare functions implement the `FnMut` trait. +//! +//! See . + +//@ run-pass + +fn call_f(mut f: F) { + f(); +} + +fn f() { + println!("hello"); +} + +fn call_g String>(mut g: G, x: String, y: String) + -> String { + g(x, y) +} + +fn g(mut x: String, y: String) -> String { + x.push_str(&y); + x +} + +fn main() { + call_f(f); + assert_eq!(call_g(g, "foo".to_string(), "bar".to_string()), + "foobar"); +} diff --git a/tests/ui/lint/overflowing-literals-valid.rs b/tests/ui/lint/overflowing-literals-valid.rs new file mode 100644 index 00000000000..08aa092ee71 --- /dev/null +++ b/tests/ui/lint/overflowing-literals-valid.rs @@ -0,0 +1,19 @@ +//! Test that valid large numeric literals do not trigger the `overflowing_literals` lint. + +//@ run-pass + +#![deny(overflowing_literals)] + +pub fn main() { + assert_eq!(0xffffffff, (!0 as u32)); + assert_eq!(4294967295, (!0 as u32)); + assert_eq!(0xffffffffffffffff, (!0 as u64)); + assert_eq!(18446744073709551615, (!0 as u64)); + + assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647); + + assert_eq!(-3.40282356e+38_f32, f32::MIN); + assert_eq!(3.40282356e+38_f32, f32::MAX); + assert_eq!(-1.7976931348623158e+308_f64, f64::MIN); + assert_eq!(1.7976931348623158e+308_f64, f64::MAX); +} diff --git a/tests/ui/methods/vec-autoderef-autoref.rs b/tests/ui/methods/vec-autoderef-autoref.rs new file mode 100644 index 00000000000..38c0ba8574b --- /dev/null +++ b/tests/ui/methods/vec-autoderef-autoref.rs @@ -0,0 +1,26 @@ +//! Test that method resolution does not autoderef `Vec` +//! into a slice or perform additional autorefs. + +fn main() { + let mut a = vec![0]; + a.test_mut(); //~ ERROR no method named `test_mut` found + a.test(); //~ ERROR no method named `test` found + + ([1]).test(); //~ ERROR no method named `test` found + (&[1]).test(); //~ ERROR no method named `test` found +} + +trait MyIter { + fn test_mut(&mut self); + fn test(&self); +} + +impl<'a> MyIter for &'a [isize] { + fn test_mut(&mut self) { } + fn test(&self) { } +} + +impl<'a> MyIter for &'a str { + fn test_mut(&mut self) { } + fn test(&self) { } +} diff --git a/tests/ui/methods/vec-autoderef-autoref.stderr b/tests/ui/methods/vec-autoderef-autoref.stderr new file mode 100644 index 00000000000..61c3bcc5b3b --- /dev/null +++ b/tests/ui/methods/vec-autoderef-autoref.stderr @@ -0,0 +1,57 @@ +error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in the current scope + --> $DIR/vec-autoderef-autoref.rs:6:7 + | +LL | a.test_mut(); + | ^^^^^^^^ + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test_mut`, perhaps you need to implement it + --> $DIR/vec-autoderef-autoref.rs:13:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ +help: there is a method `get_mut` with a similar name, but with different arguments + --> $SRC_DIR/core/src/slice/mod.rs:LL:COL + +error[E0599]: no method named `test` found for struct `Vec<{integer}>` in the current scope + --> $DIR/vec-autoderef-autoref.rs:7:7 + | +LL | a.test(); + | ^^^^ method not found in `Vec<{integer}>` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/vec-autoderef-autoref.rs:13:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ + +error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope + --> $DIR/vec-autoderef-autoref.rs:9:11 + | +LL | ([1]).test(); + | ^^^^ method not found in `[{integer}; 1]` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/vec-autoderef-autoref.rs:13:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ + +error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope + --> $DIR/vec-autoderef-autoref.rs:10:12 + | +LL | (&[1]).test(); + | ^^^^ method not found in `&[{integer}; 1]` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/vec-autoderef-autoref.rs:13:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/str/str-static-literal.rs b/tests/ui/str/str-static-literal.rs new file mode 100644 index 00000000000..61630f0f22b --- /dev/null +++ b/tests/ui/str/str-static-literal.rs @@ -0,0 +1,8 @@ +//! Check that a bare string literal is typed as a `&'static str` and is usable. + +//@ run-pass + +pub fn main() { + let x: &'static str = "foo"; + println!("{}", x); +} -- cgit 1.4.1-3-g733a5