From 12dd4a190866a94b1802b3b5d9b60055308e15bb Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 22 Feb 2025 14:59:07 -0500 Subject: [PATCH 01/15] Stabilise c_str_module --- library/alloc/src/ffi/mod.rs | 2 +- library/core/src/ffi/mod.rs | 2 +- library/std/src/ffi/mod.rs | 2 +- library/std/src/lib.rs | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/ffi/mod.rs b/library/alloc/src/ffi/mod.rs index 695d7ad07cf76..05a2763a22596 100644 --- a/library/alloc/src/ffi/mod.rs +++ b/library/alloc/src/ffi/mod.rs @@ -87,5 +87,5 @@ pub use self::c_str::CString; #[stable(feature = "alloc_c_string", since = "1.64.0")] pub use self::c_str::{FromVecWithNulError, IntoStringError, NulError}; -#[unstable(feature = "c_str_module", issue = "112134")] +#[stable(feature = "c_str_module", since = "CURRENT_RUSTC_VERSION")] pub mod c_str; diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 9bae5fd466a18..c9c73a25d899e 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -20,7 +20,7 @@ pub use self::c_str::FromBytesUntilNulError; pub use self::c_str::FromBytesWithNulError; use crate::fmt; -#[unstable(feature = "c_str_module", issue = "112134")] +#[stable(feature = "c_str_module", since = "CURRENT_RUSTC_VERSION")] pub mod c_str; #[unstable( diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 860ec3a6be16e..6e1ec72dbdb3e 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -161,7 +161,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[unstable(feature = "c_str_module", issue = "112134")] +#[stable(feature = "c_str_module", since = "CURRENT_RUSTC_VERSION")] pub mod c_str; #[stable(feature = "core_c_void", since = "1.30.0")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 0661b3d770e48..998bf32a6cef7 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -327,7 +327,6 @@ #![feature(array_chunks)] #![feature(bstr)] #![feature(bstr_internals)] -#![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] #![feature(core_intrinsics)] From 6be84b1f3863c93f87946a1efd86120966d703dc Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 22 Feb 2025 15:10:03 -0500 Subject: [PATCH 02/15] Somehow these stability attributes were able to be omitted before? --- library/alloc/src/ffi/c_str.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index fd93045a5ac4d..87625193b02aa 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -821,6 +821,7 @@ impl From>> for CString { } } +#[stable(feature = "c_string_from_str", since = "1.85.0")] impl FromStr for CString { type Err = NulError; @@ -833,6 +834,7 @@ impl FromStr for CString { } } +#[stable(feature = "c_string_from_str", since = "1.85.0")] impl TryFrom for String { type Error = IntoStringError; From 35363245657ee53a3735f1cef0df9a45e9ed44b9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Apr 2025 22:09:11 +0200 Subject: [PATCH 03/15] Fix detection of `main` function if there are expressions around it --- src/librustdoc/doctest/make.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index d5c965f7053e0..94e227b70e00c 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -407,15 +407,19 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { is_extern_crate = check_item(&item, &mut info, crate_name); } - StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { - reset_error_count(&psess); - return Err(()); + StmtKind::Expr(ref expr) => { + if matches!(expr.kind, ast::ExprKind::Err(_)) { + reset_error_count(&psess); + return Err(()); + } + has_non_module_items = true; } StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { let mut iter = mac_call.mac.args.tokens.iter(); @@ -437,7 +441,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} + // We do nothing in this case. Not marking it as `non_module_items` either. + StmtKind::Empty => {} + _ => { + has_non_module_items = true; + } } // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to @@ -462,6 +470,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { From 81438c0b05f177ae7bc0d6511d1cc507652eb241 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Apr 2025 22:09:35 +0200 Subject: [PATCH 04/15] Add regression ui test for #140162 and for #139651 --- .../doctest/test-main-alongside-exprs.rs | 22 +++++++++++++++++++ .../doctest/test-main-alongside-exprs.stdout | 6 +++++ 2 files changed, 28 insertions(+) create mode 100644 tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs create mode 100644 tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs new file mode 100644 index 0000000000000..ee2299c0fd87e --- /dev/null +++ b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs @@ -0,0 +1,22 @@ +// This test ensures that if there is an expression alongside a `main` +// function, it will not consider the entire code to be part of the `main` +// function and will generate its own function to wrap everything. +// +// This is a regression test for: +// * +// * +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +#![crate_name = "foo"] + +//! ``` +//! # if cfg!(miri) { return; } +//! use std::ops::Deref; +//! +//! fn main() { +//! println!("Hi!"); +//! } +//! ``` diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout new file mode 100644 index 0000000000000..90d7c3546bf10 --- /dev/null +++ b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/test-main-alongside-exprs.rs - (line 15) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From 8cd12bf8fa1d40edaf580dd112c9b44c4dd8dcd3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 10 Apr 2025 20:23:43 +0200 Subject: [PATCH 05/15] check types of const param default --- .../rustc_hir_analysis/src/check/wfcheck.rs | 33 +++++++++++++++++++ .../defaults/concrete-const-param-type.rs | 13 ++++++++ .../defaults/concrete-const-param-type.stderr | 25 ++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 tests/ui/const-generics/defaults/concrete-const-param-type.rs create mode 100644 tests/ui/const-generics/defaults/concrete-const-param-type.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 33d5a86beb3b0..8bb215b6b2793 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1488,6 +1488,39 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id .then(|| WellFormedLoc::Ty(param.def_id.expect_local())), default, ); + } else { + // If we've got a generic const parameter we still want to check its + // type is correct in case both it and the param type are fully concrete. + let GenericArgKind::Const(ct) = default.unpack() else { + continue; + }; + + let ct_ty = match ct.kind() { + ty::ConstKind::Infer(_) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Bound(_, _) => unreachable!(), + ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue, + ty::ConstKind::Value(cv) => cv.ty, + ty::ConstKind::Unevaluated(uv) => { + infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) + } + ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(wfcx.param_env), + }; + + let param_ty = tcx.type_of(param.def_id).instantiate_identity(); + if !ct_ty.has_param() && !param_ty.has_param() { + let cause = traits::ObligationCause::new( + tcx.def_span(param.def_id), + wfcx.body_def_id, + ObligationCauseCode::WellFormed(None), + ); + wfcx.register_obligation(Obligation::new( + tcx, + cause, + wfcx.param_env, + ty::ClauseKind::ConstArgHasType(ct, param_ty), + )); + } } } } diff --git a/tests/ui/const-generics/defaults/concrete-const-param-type.rs b/tests/ui/const-generics/defaults/concrete-const-param-type.rs new file mode 100644 index 0000000000000..c411f81192bd6 --- /dev/null +++ b/tests/ui/const-generics/defaults/concrete-const-param-type.rs @@ -0,0 +1,13 @@ +#![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)] +//~^ WARN the feature `generic_const_parameter_types` is incomplete +//~| WARN the feature `unsized_const_params` is incomplete +// Make sure that we test the const param type of default const parameters +// if both the type of the default and the type of the parameter are concrete. + +use std::marker::ConstParamTy_; + +struct Foo; //~ ERROR the constant `N` is not of type `u64` +struct Bar(T); // ok +struct Baz(T); // ok + +fn main() {} diff --git a/tests/ui/const-generics/defaults/concrete-const-param-type.stderr b/tests/ui/const-generics/defaults/concrete-const-param-type.stderr new file mode 100644 index 0000000000000..ad077f87e5dfb --- /dev/null +++ b/tests/ui/const-generics/defaults/concrete-const-param-type.stderr @@ -0,0 +1,25 @@ +warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/concrete-const-param-type.rs:1:12 + | +LL | #![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #137626 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/concrete-const-param-type.rs:1:43 + | +LL | #![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + +error: the constant `N` is not of type `u64` + --> $DIR/concrete-const-param-type.rs:9:26 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^^^ expected `u64`, found `u32` + +error: aborting due to 1 previous error; 2 warnings emitted + From f319dd909ed3ec1c0d04ede06b5864badddefb15 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 20 Apr 2025 15:45:30 +0530 Subject: [PATCH 06/15] add llvm wrappers and corresponding methods in attribute --- compiler/rustc_codegen_llvm/src/attributes.rs | 16 ++++++++++++++++ .../rustc_codegen_llvm/src/llvm/enzyme_ffi.rs | 9 +++++++++ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 19 +++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index e8c42d16733ec..545708384d9df 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -28,6 +28,22 @@ pub(crate) fn apply_to_callsite(callsite: &Value, idx: AttributePlace, attrs: &[ } } +pub(crate) fn has_attr(llfn: &Value, idx: AttributePlace, attr: AttributeKind) -> bool { + llvm::HasAttributeAtIndex(llfn, idx, attr) +} + +pub(crate) fn has_string_attr(llfn: &Value, name: *const i8) -> bool { + llvm::HasStringAttribute(llfn, name) +} + +pub(crate) fn remove_from_llfn(llfn: &Value, place: AttributePlace, kind: AttributeKind) { + llvm::RemoveRustEnumAttributeAtIndex(llfn, place, kind); +} + +pub(crate) fn remove_string_attr_from_llfn(llfn: &Value, name: *const i8) { + llvm::RemoveStringAttrFromFn(llfn, name); +} + /// Get LLVM attribute for the provided inline heuristic. #[inline] fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll Attribute> { diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index a9b3bdf7344be..08987a3ad14dd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -19,6 +19,15 @@ unsafe extern "C" { pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool; pub(crate) fn LLVMRustHasAttributeAtIndex(V: &Value, i: c_uint, Kind: AttributeKind) -> bool; pub(crate) fn LLVMRustGetArrayNumElements(Ty: &Type) -> u64; + pub(crate) fn LLVMRustHasFnAttribute(F: &Value, Name: *const c_char) -> bool; + pub(crate) fn LLVMRustRemoveFnAttribute(F: &Value, Name: *const c_char); + pub(crate) fn LLVMGetFirstFunction(M: &Module) -> Option<&Value>; + pub(crate) fn LLVMGetNextFunction(Fn: &Value) -> Option<&Value>; + pub(crate) fn LLVMRustRemoveEnumAttributeAtIndex( + Fn: &Value, + index: c_uint, + kind: AttributeKind, + ); } unsafe extern "C" { diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 5f0e4d745e833..2871b3c02936e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -973,6 +973,25 @@ extern "C" LLVMMetadataRef LLVMRustDIGetInstMetadata(LLVMValueRef x) { return nullptr; } +extern "C" void +LLVMRustRemoveEnumAttributeAtIndex(LLVMValueRef F, size_t index, + LLVMRustAttributeKind RustAttr) { + LLVMRemoveEnumAttributeAtIndex(F, index, fromRust(RustAttr)); +} + +extern "C" bool LLVMRustHasFnAttribute(LLVMValueRef F, const char *Name) { + if (auto *Fn = dyn_cast(unwrap(F))) { + return Fn->hasFnAttribute(Name); + } + return false; +} + +extern "C" void LLVMRustRemoveFnAttribute(LLVMValueRef Fn, const char *Name) { + if (auto *F = dyn_cast(unwrap(Fn))) { + F->removeFnAttr(Name); + } +} + extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) { unwrap(Global)->addMetadata(Kind, *unwrap(MD)); From 9bc04016e6dffd6398ea62f05b9320e0198ab0be Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 20 Apr 2025 15:48:58 +0530 Subject: [PATCH 07/15] add custom enzyme markers to target methods --- compiler/rustc_codegen_llvm/src/builder/autodiff.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 0147bd5a66581..c5c13ac097a27 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -361,6 +361,11 @@ fn generate_enzyme_call<'ll>( let attr = llvm::AttributeKind::NoInline.create_attr(cx.llcx); attributes::apply_to_llfn(ad_fn, Function, &[attr]); + // We add a made-up attribute just such that we can recognize it after AD to update + // (no)-inline attributes. We'll then also remove this attribute. + let enzyme_marker_attr = llvm::CreateAttrString(cx.llcx, "enzyme_marker"); + attributes::apply_to_llfn(outer_fn, Function, &[enzyme_marker_attr]); + // first, remove all calls from fnc let entry = llvm::LLVMGetFirstBasicBlock(outer_fn); let br = llvm::LLVMRustGetTerminator(entry); From 48d05aac9b9aa488702b5519fd16121336468593 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 20 Apr 2025 15:54:12 +0530 Subject: [PATCH 08/15] remove noinline attribute and add alwaysinline after AD pass --- compiler/rustc_codegen_llvm/src/back/lto.rs | 30 ++++++++++++++++++++- compiler/rustc_codegen_llvm/src/context.rs | 10 +++++++ compiler/rustc_codegen_llvm/src/llvm/mod.rs | 26 ++++++++++++++++++ compiler/rustc_codegen_llvm/src/type_.rs | 4 +++ tests/codegen/autodiff/inline.rs | 23 ++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tests/codegen/autodiff/inline.rs diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 925898d817371..9f00a4c27c341 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -28,8 +28,9 @@ use crate::back::write::{ use crate::errors::{ DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, LtoProcMacro, }; +use crate::llvm::AttributePlace::Function; use crate::llvm::{self, build_string}; -use crate::{LlvmCodegenBackend, ModuleLlvm}; +use crate::{LlvmCodegenBackend, ModuleLlvm, SimpleCx, attributes}; /// We keep track of the computed LTO cache keys from the previous /// session to determine which CGUs we can reuse. @@ -666,6 +667,33 @@ pub(crate) fn run_pass_manager( } if cfg!(llvm_enzyme) && enable_ad && !thin { + let cx = + SimpleCx::new(module.module_llvm.llmod(), &module.module_llvm.llcx, cgcx.pointer_size); + + for function in cx.get_functions() { + let enzyme_marker = CString::new("enzyme_marker").unwrap(); + let marker_ptr = enzyme_marker.as_ptr(); + + if attributes::has_string_attr(function, marker_ptr) { + // Sanity check: Ensure 'noinline' is present before replacing it. + assert!( + !attributes::has_attr(function, Function, llvm::AttributeKind::NoInline), + "Expected __enzyme function to have 'noinline' before adding 'alwaysinline'" + ); + + attributes::remove_from_llfn(function, Function, llvm::AttributeKind::NoInline); + attributes::remove_string_attr_from_llfn(function, marker_ptr); + + assert!( + !attributes::has_string_attr(function, marker_ptr), + "Expected function to not have 'enzyme_marker'" + ); + + let always_inline = llvm::AttributeKind::AlwaysInline.create_attr(cx.llcx); + attributes::apply_to_llfn(function, Function, &[always_inline]); + } + } + let opt_stage = llvm::OptStage::FatLTO; let stage = write::AutodiffStage::PostAD; if !config.autodiff.contains(&config::AutoDiff::NoPostopt) { diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 4ec6999551898..ed50515b70716 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -698,6 +698,16 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { llvm::LLVMMDStringInContext2(self.llcx(), name.as_ptr() as *const c_char, name.len()) }) } + + pub(crate) fn get_functions(&self) -> Vec<&'ll Value> { + let mut functions = vec![]; + let mut func = unsafe { llvm::LLVMGetFirstFunction(self.llmod()) }; + while let Some(f) = func { + functions.push(f); + func = unsafe { llvm::LLVMGetNextFunction(f) } + } + functions + } } impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 6ca81c651ed42..d401440f3aef1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -41,6 +41,32 @@ pub(crate) fn AddFunctionAttributes<'ll>( } } +pub(crate) fn HasAttributeAtIndex<'ll>( + llfn: &'ll Value, + idx: AttributePlace, + kind: AttributeKind, +) -> bool { + unsafe { LLVMRustHasAttributeAtIndex(llfn, idx.as_uint(), kind) } +} + +pub(crate) fn HasStringAttribute<'ll>(llfn: &'ll Value, name: *const i8) -> bool { + unsafe { LLVMRustHasFnAttribute(llfn, name) } +} + +pub(crate) fn RemoveStringAttrFromFn<'ll>(llfn: &'ll Value, name: *const i8) { + unsafe { LLVMRustRemoveFnAttribute(llfn, name) } +} + +pub(crate) fn RemoveRustEnumAttributeAtIndex( + llfn: &Value, + place: AttributePlace, + kind: AttributeKind, +) { + unsafe { + LLVMRustRemoveEnumAttributeAtIndex(llfn, place.as_uint(), kind); + } +} + pub(crate) fn AddCallSiteAttributes<'ll>( callsite: &'ll Value, idx: AttributePlace, diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index b89ce90d1a1dc..169036f515298 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -128,6 +128,10 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { (**self).borrow().llcx } + pub(crate) fn llmod(&self) -> &'ll llvm::Module { + (**self).borrow().llmod + } + pub(crate) fn isize_ty(&self) -> &'ll Type { (**self).borrow().isize_ty } diff --git a/tests/codegen/autodiff/inline.rs b/tests/codegen/autodiff/inline.rs new file mode 100644 index 0000000000000..e90faa4aa3802 --- /dev/null +++ b/tests/codegen/autodiff/inline.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat -Zautodiff=NoPostopt +//@ no-prefer-dynamic +//@ needs-enzyme + +#![feature(autodiff)] + +use std::autodiff::autodiff; + +#[autodiff(d_square, Reverse, Duplicated, Active)] +fn square(x: &f64) -> f64 { + x * x +} + +// CHECK: ; inline::d_square +// CHECK-NEXT: ; Function Attrs: alwaysinline +// CHECK-NOT: noinline +// CHECK-NEXT: define internal fastcc void @_ZN6inline8d_square17h021c74e92c259cdeE +fn main() { + let x = std::hint::black_box(3.0); + let mut dx1 = std::hint::black_box(1.0); + let _ = d_square(&x, &mut dx1, 1.0); + assert_eq!(dx1, 6.0); +} From 3ededc1053f752d993a0b25286faebfe3616819d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Apr 2025 22:01:00 +0200 Subject: [PATCH 09/15] Improve code --- src/librustdoc/doctest/make.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 94e227b70e00c..c46c6d71491a3 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -407,7 +407,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> Result { let mut iter = mac_call.mac.args.tokens.iter(); @@ -444,7 +447,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} _ => { - has_non_module_items = true; + has_non_items = true; } } @@ -470,7 +473,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result Date: Fri, 25 Apr 2025 22:04:50 +0200 Subject: [PATCH 10/15] If there is a `;` alone, we consider that the doctest needs to be put inside a function --- src/librustdoc/doctest/make.rs | 2 -- .../failed-doctest-extra-semicolon-on-item.rs | 4 +-- ...led-doctest-extra-semicolon-on-item.stdout | 27 ++----------------- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index c46c6d71491a3..e41a06aff3036 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -444,8 +444,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} _ => { has_non_items = true; } diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs index 508faadcf6729..ca5dd78746789 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs @@ -4,12 +4,12 @@ //@ compile-flags:--test //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ failure-status: 101 +//@ check-pass /// /// /// ```rust -/// struct S {}; // unexpected semicolon after struct def +/// struct S {}; /// /// fn main() { /// assert_eq!(0, 1); diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout index 9eb8b391e7809..1068b98cb0fbb 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout @@ -1,29 +1,6 @@ running 1 test -test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... FAILED +test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... ok -failures: - ----- $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) stdout ---- -error: expected item, found `;` - --> $DIR/failed-doctest-extra-semicolon-on-item.rs:12:12 - | -LL | struct S {}; // unexpected semicolon after struct def - | ^ - | - = help: braced struct declarations are not followed by a semicolon -help: remove this semicolon - | -LL - struct S {}; // unexpected semicolon after struct def -LL + struct S {} // unexpected semicolon after struct def - | - -error: aborting due to 1 previous error - -Couldn't compile the test. - -failures: - $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) - -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME From 59b6cf5332e837b328193ba4f27f98e1f794a24d Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 20 Mar 2025 12:04:07 +0530 Subject: [PATCH 11/15] uefi: Update r-efi - Bump up the version to 5.2.0 Signed-off-by: Ayush Singh --- library/Cargo.lock | 8 ++++---- library/std/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index f7f09a11f3ac9..c21dec14986fa 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -257,9 +257,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "4.5.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -267,9 +267,9 @@ dependencies = [ [[package]] name = "r-efi-alloc" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7" +checksum = "e43c53ff1a01d423d1cb762fd991de07d32965ff0ca2e4f80444ac7804198203" dependencies = [ "compiler_builtins", "r-efi", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 3536e84d58bed..602af4a0447ee 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -83,8 +83,8 @@ wasi = { version = "0.11.0", features = [ ], default-features = false } [target.'cfg(target_os = "uefi")'.dependencies] -r-efi = { version = "4.5.0", features = ['rustc-dep-of-std'] } -r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] } +r-efi = { version = "5.2.0", features = ['rustc-dep-of-std'] } +r-efi-alloc = { version = "2.0.0", features = ['rustc-dep-of-std'] } [features] backtrace = [ From 43d8d89b9ef6ce10d3310fdb56fb850dc8b42c91 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Sat, 26 Apr 2025 13:48:22 +0500 Subject: [PATCH 12/15] clarified bootstrap optimization agrs --- bootstrap.example.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 72c4492d465d8..72fd56fb5bd71 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -500,7 +500,7 @@ # building without optimizations takes much longer than optimizing. Further, some platforms # fail to build without this optimization (c.f. #65352). # The valid options are: -# true - Enable optimizations. +# true - Enable optimizations (same as 3). # false - Disable optimizations. # 0 - Disable optimizations. # 1 - Basic optimizations. From 86969dbe773b6e3f05ab34e9a2f8ba08441ebf88 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 26 Apr 2025 18:42:15 +0300 Subject: [PATCH 13/15] session: Cleanup `CanonicalizedPath::new` It wants an owned path, so pass an owned path --- compiler/rustc_interface/src/tests.rs | 8 ++++---- compiler/rustc_session/src/config.rs | 3 +-- compiler/rustc_session/src/utils.rs | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 5c8c51c8bbcc2..0ceda2201344e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -1,7 +1,7 @@ #![allow(rustc::bad_opt_access)] -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::num::NonZero; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::atomic::AtomicBool; use rustc_abi::Align; @@ -89,8 +89,8 @@ where S: Into, I: IntoIterator, { - let locations: BTreeSet = - locations.into_iter().map(|s| CanonicalizedPath::new(Path::new(&s.into()))).collect(); + let locations = + locations.into_iter().map(|s| CanonicalizedPath::new(PathBuf::from(s.into()))).collect(); ExternEntry { location: ExternLocation::ExactPaths(locations), diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 43955cc23a9e9..e2d36f6a4e2ff 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2323,14 +2323,13 @@ pub fn parse_externs( let ExternOpt { crate_name: name, path, options } = split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit()); - let path = path.map(|p| CanonicalizedPath::new(p.as_path())); - let entry = externs.entry(name.to_owned()); use std::collections::btree_map::Entry; let entry = if let Some(path) = path { // --extern prelude_name=some_file.rlib + let path = CanonicalizedPath::new(path); match entry { Entry::Vacant(vacant) => { let files = BTreeSet::from_iter(iter::once(path)); diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 2243e831b66ec..e9ddd66b5e8b3 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::OnceLock; use rustc_data_structures::profiling::VerboseTimingGuard; @@ -104,8 +104,8 @@ pub struct CanonicalizedPath { } impl CanonicalizedPath { - pub fn new(path: &Path) -> Self { - Self { original: path.to_owned(), canonicalized: try_canonicalize(path).ok() } + pub fn new(path: PathBuf) -> Self { + Self { canonicalized: try_canonicalize(&path).ok(), original: path } } pub fn canonicalized(&self) -> &PathBuf { From 9112c86f4226a6922f07bb44b49cedb75d1ee2f9 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Fri, 25 Apr 2025 11:27:01 -0400 Subject: [PATCH 14/15] Update example to use `CStr::to_string_lossy` --- library/core/src/ffi/c_str.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 85e87445a1b43..ac07c645c0195 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -79,8 +79,9 @@ use crate::{fmt, ops, slice, str}; /// /// fn my_string_safe() -> String { /// let cstr = unsafe { CStr::from_ptr(my_string()) }; -/// // Get copy-on-write Cow<'_, str>, then guarantee a freshly-owned String allocation -/// String::from_utf8_lossy(cstr.to_bytes()).to_string() +/// // Get a copy-on-write Cow<'_, str>, then extract the +/// // allocated String (or allocate a fresh one if needed). +/// cstr.to_string_lossy().into_owned() /// } /// /// println!("string: {}", my_string_safe()); From aa69e3a0cb8f1b2e086709a038baad6f39249150 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 27 Apr 2025 00:12:32 +0200 Subject: [PATCH 15/15] Fix bad handling of macros if there is already a `main` function --- src/librustdoc/doctest/make.rs | 5 ++++- .../doctest/auxiliary/macro-after-main.rs | 1 + tests/rustdoc-ui/doctest/macro-after-main.rs | 16 ++++++++++++++++ tests/rustdoc-ui/doctest/macro-after-main.stdout | 6 ++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs create mode 100644 tests/rustdoc-ui/doctest/macro-after-main.rs create mode 100644 tests/rustdoc-ui/doctest/macro-after-main.stdout diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index e41a06aff3036..4194abc8d5742 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -424,7 +424,10 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { + StmtKind::MacCall(ref mac_call) => { + if info.has_main_fn { + continue; + } let mut iter = mac_call.mac.args.tokens.iter(); while let Some(token) = iter.next() { diff --git a/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs b/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs new file mode 100644 index 0000000000000..ed7584b742533 --- /dev/null +++ b/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs @@ -0,0 +1 @@ +use std::string::String; diff --git a/tests/rustdoc-ui/doctest/macro-after-main.rs b/tests/rustdoc-ui/doctest/macro-after-main.rs new file mode 100644 index 0000000000000..0a42343f1c272 --- /dev/null +++ b/tests/rustdoc-ui/doctest/macro-after-main.rs @@ -0,0 +1,16 @@ +// This test checks a corner case where the macro calls used to be skipped, +// making them considered as statement, and therefore some cases where +// `include!` macro was then put into a function body, making the doctest +// compilation fail. + +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +//! ``` +//! include!("./auxiliary/macro-after-main.rs"); +//! +//! fn main() {} +//! eprintln!(); +//! ``` diff --git a/tests/rustdoc-ui/doctest/macro-after-main.stdout b/tests/rustdoc-ui/doctest/macro-after-main.stdout new file mode 100644 index 0000000000000..72ffe2b5a27c5 --- /dev/null +++ b/tests/rustdoc-ui/doctest/macro-after-main.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/macro-after-main.rs - (line 11) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +