From 3b3ba8b5e45eddb8456d3ab3eb82d0d41e32ea77 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 30 Aug 2026 09:33:14 +0200 Subject: [PATCH 01/24] peel_transparent_wrappers only works on non-1ZST --- compiler/rustc_abi/src/layout/ty.rs | 19 +++++++++++++++---- compiler/rustc_codegen_llvm/src/va_arg.rs | 4 ++-- compiler/rustc_codegen_ssa/src/mir/place.rs | 6 ++++-- .../rustc_codegen_ssa/src/traits/builder.rs | 13 +++++++------ .../src/hir_ty_lowering/cmse.rs | 2 +- compiler/rustc_target/src/callconv/s390x.rs | 3 ++- compiler/rustc_target/src/callconv/wasm.rs | 7 +++++-- compiler/rustc_target/src/callconv/x86.rs | 3 ++- 8 files changed, 38 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index b8928aecf0cc5..0bc8f7e13ee2c 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -247,15 +247,25 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { where Ty: TyAbiInterface<'a, C> + Copy, { - let base = self.peel_transparent_wrappers(cx); + // FIXME: Peeling the wrappers above would not work correctly if we are a 1-ZST. So we make + // `#[rustc_pass_indirectly_in_non_rustic_abis]` a NOP on 1-ZST. In the future, + // `non_1zst_field` should become `non_trivial_abi_field` and + // `#[rustc_pass_indirectly_in_non_rustic_abis]` should make a type have non-trivial ABI. + if self.is_1zst() { + return false; + } + + let base = self.peel_transparent_wrappers_from_non_1zst(cx); Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base) } /// Recursively peel away transparent wrappers, returning the inner value. + /// Will not peel anything if `self` is a 1-ZST! Callers need to either check + /// that the result is not a 1-ZST, or have separate logic for that. /// /// The return value is not `repr(transparent)` and/or does /// not have a non-1zst field. - pub fn peel_transparent_wrappers(mut self, cx: &C) -> Self + pub fn peel_transparent_wrappers_from_non_1zst(mut self, cx: &C) -> Self where Ty: TyAbiInterface<'a, C> + Copy, { @@ -321,12 +331,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { where Ty: TyAbiInterface<'a, C> + Copy, { - let complex = self.peel_transparent_wrappers(cx); + // We're checking for scalar repr below which excludes 1-ZST. + let complex = self.peel_transparent_wrappers_from_non_1zst(cx); if !Ty::is_complex_number_lang_item(complex, cx) { return None; } - let component = complex.field(cx, 0).peel_transparent_wrappers(cx); + let component = complex.field(cx, 0).peel_transparent_wrappers_from_non_1zst(cx); let BackendRepr::Scalar(scalar) = component.backend_repr else { return None; diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 2a02df05f26f5..c6bce87252d16 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -308,7 +308,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( let va_list_addr = list.immediate(); // Peel off any newtype wrappers. - let layout = layout.peel_transparent_wrappers(bx.cx); + let layout = layout.peel_transparent_wrappers_from_non_1zst(bx.cx); // Rust does not currently support any powerpc softfloat targets. let target = &bx.cx.tcx.sess.target; @@ -561,7 +561,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( // #[repr(C)] // struct Foo([Empty; 8], i32); // ``` - let layout = layout.peel_transparent_wrappers(bx.cx); + let layout = layout.peel_transparent_wrappers_from_non_1zst(bx.cx); // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed // in the registers. If not go to step 7. diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 02e125fd31717..486b13cafdccb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -112,7 +112,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, layout: TyAndLayout<'tcx>, ) -> Self { - if layout.peel_transparent_wrappers(bx).deref().is_scalable_vector() { + // Scalable vector are never 1-ZST. FIXME: is that correct? + if layout.peel_transparent_wrappers_from_non_1zst(bx).deref().is_scalable_vector() { Self::alloca_scalable(bx, layout) } else { Self::alloca_size(bx, layout.size, layout) @@ -159,7 +160,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { layout: TyAndLayout<'tcx>, ) -> Self { PlaceValue::new_sized( - bx.alloca_with_ty(layout.peel_transparent_wrappers(bx)), + // FIXME why is this peeling at all? And why is it redoing the work the caller just did? + bx.alloca_with_ty(layout.peel_transparent_wrappers_from_non_1zst(bx)), layout.align.abi, ) .with_type(layout) diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index b7b694922bcfa..afe3aec13d279 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -539,12 +539,13 @@ pub trait BuilderMethods<'a, 'tcx>: let tt = tt.add_indirection(); let fnc_tree = FncTree { args: vec![tt.clone(), tt], ret: TypeTree::new() }; let bytes = self.const_usize(layout.size.bytes()); - let bytes = if layout.peel_transparent_wrappers(self).ty.is_scalable_vector() { - let vscale = self.vscale(self.type_i64()); - self.mul(vscale, bytes) - } else { - bytes - }; + let bytes = + if layout.peel_transparent_wrappers_from_non_1zst(self).ty.is_scalable_vector() { + let vscale = self.vscale(self.type_i64()); + self.mul(vscale, bytes) + } else { + bytes + }; self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags, Some(fnc_tree)); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 675e7e3c2a02a..530706b0653db 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -170,7 +170,7 @@ fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, layout: TyAndLayout<'tc // Accept (transparently wrapped) scalar 64-bit primitives. matches!( - layout.peel_transparent_wrappers(&cx).ty.kind(), + layout.peel_transparent_wrappers_from_non_1zst(&cx).ty.kind(), ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64) ) } diff --git a/compiler/rustc_target/src/callconv/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs index 0d29bc658b56d..146cfc3c6ee65 100644 --- a/compiler/rustc_target/src/callconv/s390x.rs +++ b/compiler/rustc_target/src/callconv/s390x.rs @@ -15,7 +15,8 @@ where // Contrary to X86, trailing padding is allowed on s390x. loop { - layout = layout.peel_transparent_wrappers(cx); + // We're only looking for scalar types that are non-ZST. + layout = layout.peel_transparent_wrappers_from_non_1zst(cx); return match layout.backend_repr { BackendRepr::Scalar(scalar) => match scalar.primitive() { diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs index 3706caa6b6f44..237bc2960b17e 100644 --- a/compiler/rustc_target/src/callconv/wasm.rs +++ b/compiler/rustc_target/src/callconv/wasm.rs @@ -11,7 +11,8 @@ where C: HasDataLayout, { // The base case: a single scalar is a singleton scalar. - if !(layout.is_aggregate() || layout.peel_transparent_wrappers(cx).is_enum()) { + // We're only looking for scalar types that are non-ZST. + if !(layout.is_aggregate() || layout.peel_transparent_wrappers_from_non_1zst(cx).is_enum()) { let BackendRepr::Scalar(scalar) = layout.backend_repr else { return None; }; @@ -62,7 +63,9 @@ where { // An enum that is represented as an integer is not an aggregate to rust, but may still // need to be passed as one if its variants have any (even ZST) fields. - if !(val.layout.is_aggregate() || val.layout.peel_transparent_wrappers(cx).is_enum()) { + if !(val.layout.is_aggregate() + || val.layout.peel_transparent_wrappers_from_non_1zst(cx).is_enum()) + { return false; } diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 3476f41e3bc75..147d499d2c76b 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -15,7 +15,8 @@ where let outer_size = layout.layout.size(); loop { - layout = layout.peel_transparent_wrappers(cx); + // We're only looking for scalar types that are non-ZST. + layout = layout.peel_transparent_wrappers_from_non_1zst(cx); return match layout.backend_repr { BackendRepr::Scalar(scalar) => match scalar.primitive() { From 6e8947a4a5e790d360cc561167b1b84f0eaa288a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Sep 2026 16:14:36 +0200 Subject: [PATCH 02/24] leave a comment for some sve hacks --- compiler/rustc_codegen_ssa/src/mir/place.rs | 6 ++++-- compiler/rustc_codegen_ssa/src/traits/builder.rs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 486b13cafdccb..1412f64ac2179 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -112,7 +112,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, layout: TyAndLayout<'tcx>, ) -> Self { - // Scalable vector are never 1-ZST. FIXME: is that correct? + // FIXME(rustc_scalable_vector/stdarch_aarch64_sve): Scalable vectors aren't actually sized, + // but we pretend they are. Here we have to hack around that. if layout.peel_transparent_wrappers_from_non_1zst(bx).deref().is_scalable_vector() { Self::alloca_scalable(bx, layout) } else { @@ -160,7 +161,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { layout: TyAndLayout<'tcx>, ) -> Self { PlaceValue::new_sized( - // FIXME why is this peeling at all? And why is it redoing the work the caller just did? + // FIXME why is this peeling at all? The LLVM type should be the same for the + // transparent wrapper and the inner type. bx.alloca_with_ty(layout.peel_transparent_wrappers_from_non_1zst(bx)), layout.align.abi, ) diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index afe3aec13d279..473a856b05efe 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -540,6 +540,8 @@ pub trait BuilderMethods<'a, 'tcx>: let fnc_tree = FncTree { args: vec![tt.clone(), tt], ret: TypeTree::new() }; let bytes = self.const_usize(layout.size.bytes()); let bytes = + // FIXME(rustc_scalable_vector/stdarch_aarch64_sve): Scalable vectors aren't + // actually sized, but we pretend they are. Here we have to hack around that. if layout.peel_transparent_wrappers_from_non_1zst(self).ty.is_scalable_vector() { let vscale = self.vscale(self.type_i64()); self.mul(vscale, bytes) From 5e9dca942e3199372459d3d9f043aa53b31df518 Mon Sep 17 00:00:00 2001 From: xonx <119700621+xonx4l@users.noreply.github.com> Date: Fri, 25 Sep 2026 17:52:52 +0000 Subject: [PATCH 03/24] cache results in improper_ctypes lint --- .../rustc_lint/src/types/improper_ctypes.rs | 57 ++++++++++++++++--- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index e7fa0fe2960db..2d42e9fdd05da 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -1,3 +1,4 @@ +use std::cell::RefCell; use std::iter; use std::ops::ControlFlow; @@ -5,10 +6,11 @@ use bitflags::bitflags; use rustc_abi::VariantIdx; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{DiagMessage, msg}; +use rustc_hashes::Hash128; use rustc_hir::def::CtorKind; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, AmbigArg}; -use rustc_lint_defs::{declare_lint, declare_lint_pass}; +use rustc_lint_defs::{declare_lint, impl_lint_pass}; use rustc_middle::ty::{ self, Adt, AdtDef, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, Unnormalized, @@ -131,7 +133,25 @@ declare_lint! { "Structs do not follow the power alignment rule under repr(C)" } -declare_lint_pass!(ImproperCTypesLint => [ +/// Remembers types we already checked and found FFI-safe, so we don't check the +/// same type again every time it shows up in another function. +/// We only remember "safe" types, never "unsafe" ones. That way we never need to +/// keep the actual type around, just a fingerprint of it. +#[derive(Default)] +pub(crate) struct ImproperCTypesLint { + /// A fingerprint of the type, not the type itself. Uses a big 128-bit + /// fingerprint (not a smaller 64-bit one) so two different types can't + /// accidentally get treated as the same one. + known_safe: RefCell>, +} + +impl<'tcx> ImproperCTypesLint { + fn cache_key(cx: &LateContext<'tcx>, ty: Ty<'tcx>, flags: RootUseFlags) -> (Hash128, u8) { + (cx.tcx.type_id_hash(ty), flags.bits()) + } +} + +impl_lint_pass!(ImproperCTypesLint => [ IMPROPER_CTYPES, IMPROPER_CTYPES_DEFINITIONS, USES_POWER_ALIGNMENT @@ -1102,8 +1122,16 @@ impl<'tcx> ImproperCTypesLint { fn check_foreign_static(&mut self, cx: &LateContext<'tcx>, id: hir::OwnerId, span: Span) { let ty = cx.tcx.type_of(id).instantiate_identity(); + let state = VisitorState::static_entry_point(); + let key = Self::cache_key(cx, ty.skip_norm_wip(), state.root_use_flags); + if self.known_safe.borrow().contains(&key) { + return; + } let mut visitor = ImproperCTypesVisitor::new(cx, ty, CItemKind::Declaration); - let ffi_res = visitor.check_type(VisitorState::static_entry_point(), ty); + let ffi_res = visitor.check_type(state, ty); + if matches!(ffi_res, FfiResult::FfiSafe) { + self.known_safe.borrow_mut().insert(key); + } self.process_ffi_result(cx, span, ffi_res, CItemKind::Declaration); } @@ -1119,19 +1147,32 @@ impl<'tcx> ImproperCTypesLint { let sig = cx.tcx.instantiate_bound_regions_with_erased(sig); for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { - let input_ty = Unnormalized::new_wip(*input_ty); let state = VisitorState::fn_entry_point(fn_mode, FnPos::Arg); + let key = Self::cache_key(cx, *input_ty, state.root_use_flags); + if self.known_safe.borrow().contains(&key) { + continue; + } + let input_ty = Unnormalized::new_wip(*input_ty); let mut visitor = ImproperCTypesVisitor::new(cx, input_ty, fn_mode); let ffi_res = visitor.check_type(state, input_ty); + if matches!(ffi_res, FfiResult::FfiSafe) { + self.known_safe.borrow_mut().insert(key); + } self.process_ffi_result(cx, input_hir.span, ffi_res, fn_mode); } if let hir::FnRetTy::Return(ret_hir) = decl.output { - let output_ty = Unnormalized::new_wip(sig.output()); let state = VisitorState::fn_entry_point(fn_mode, FnPos::Ret); - let mut visitor = ImproperCTypesVisitor::new(cx, output_ty, fn_mode); - let ffi_res = visitor.check_type(state, output_ty); - self.process_ffi_result(cx, ret_hir.span, ffi_res, fn_mode); + let key = Self::cache_key(cx, sig.output(), state.root_use_flags); + if !self.known_safe.borrow().contains(&key) { + let output_ty = Unnormalized::new_wip(sig.output()); + let mut visitor = ImproperCTypesVisitor::new(cx, output_ty, fn_mode); + let ffi_res = visitor.check_type(state, output_ty); + if matches!(ffi_res, FfiResult::FfiSafe) { + self.known_safe.borrow_mut().insert(key); + } + self.process_ffi_result(cx, ret_hir.span, ffi_res, fn_mode); + } } } From 30c3ff8f16ac656692ebaab7dafbbfa78d704be5 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Thu, 1 Oct 2026 13:12:58 +0200 Subject: [PATCH 04/24] abby: ensure forall where clause lhs is alias, placeholder, or lifetime --- .../rustc_hir_analysis/src/check/wfcheck.rs | 61 +++++++++++--- compiler/rustc_hir_analysis/src/collect.rs | 80 ++++++++----------- .../test-infra-fails-properly.rs | 16 +++- .../test-infra-fails-properly.stderr | 46 ++++++++--- .../test-infra-works.rs | 8 ++ 5 files changed, 141 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index dc4b6a6fd319c..6b72f6fd90605 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2423,15 +2423,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { fn check_test_binder_forall(&self, forall: TestBinderForall<'tcx>) { self.infcx.enter_forall(forall.binder, |body| { let u = self.infcx.universe(); - let mut builder = TransitiveRelationBuilder::default(); - for &(r1, r2) in &body.region_outlives { - builder.add(r1, r2); - } - // Deliberately unelaborated: the assumptions of a `forall` are exactly the ones - // written down in the test, no extra ones hidden behind the scenes. - let assumptions = ty::region_constraint::Assumptions::new_unelaborated( + let assumptions = self.build_test_binder_assumptions( + forall.span, body.type_outlives, - builder.freeze(), + body.region_outlives, ); self.infcx.insert_placeholder_assumptions(u, assumptions); self.check_test_binder_body(body.value); @@ -2449,6 +2444,52 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { }); } + fn build_test_binder_assumptions( + &self, + span: Span, + type_outlives: Vec>, + region_outlives: Vec>, + ) -> ty::region_constraint::Assumptions> { + for clause in &type_outlives { + if !matches!( + clause.skip_binder().0.kind(), + ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) + ) { + let mut err = self.tcx().dcx().struct_span_err( + span, + "the lhs of a forall where clause must be \ + an alias, placeholder, or lifetime", + ); + err.note(format!("the bad clause is {clause}")); + err.emit(); + } + } + let ty = type_outlives.iter().map(|c| c.map_bound(ty::ClauseKind::TypeOutlives)); + let reg = + region_outlives.iter().map(|&c| ty::Binder::dummy(ty::ClauseKind::RegionOutlives(c))); + let explicit_clauses: Vec> = + ty.chain(reg).map(|c| c.upcast(self.tcx())).collect(); + for elaborated in ty::elaborate::elaborate(self.tcx(), explicit_clauses.iter().copied()) { + if !explicit_clauses.contains(&elaborated) { + let mut err = self.tcx().dcx().struct_span_err( + span, + "all implied bounds of clauses must themselves be \ + included in the where clause of a forall", + ); + err.note(format!("missing clause is {elaborated}")); + err.emit(); + } + } + + let mut builder = TransitiveRelationBuilder::default(); + for &ty::OutlivesClause(r1, r2) in ®ion_outlives { + builder.add(r1, r2); + } + // Deliberately unelaborated: the assumptions of a `forall` are exactly the ones + // written down in the test, no extra ones hidden behind the scenes. + ty::region_constraint::Assumptions::new_unelaborated(type_outlives, builder.freeze()) + } + #[instrument(level = "debug", skip(self))] fn check_test_binder_region_constraints( &self, @@ -2742,6 +2783,6 @@ pub(crate) struct WithWhereClauses<'tcx, T> { // The where clauses on the forall. These eventually will probably get stored inside // `ty::Binder` but they're here for now. - pub type_outlives: Vec>>>, - pub region_outlives: Vec<(ty::Region<'tcx>, ty::Region<'tcx>)>, + pub type_outlives: Vec>, + pub region_outlives: Vec>, } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 1cd1fc356ca7d..9bac109664c6a 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -372,62 +372,50 @@ impl<'tcx> ItemCtxt<'tcx> { TestBinderExists { span: exists.span, binder } } - // FIXME: this is likely too basic, and we'll want to evolve/make this more advanced over time. - // For example, right now, if the user writes `forall<'a> where Foo<'a>: 'b`, that's not gonna - // work - that should be destructured into `where 'a: 'b`, whether by hand (and checked it was - // indeed done so, via compiler) or automatically by the test framework, unsure, but something. fn lower_test_binder_assumptions( &self, predicate: &hir::WherePredicate<'tcx>, - type_outlives: &mut Vec>>>, - region_outlives: &mut Vec<(ty::Region<'tcx>, ty::Region<'tcx>)>, + type_outlives: &mut Vec>, + region_outlives: &mut Vec>, ) { + fn outlives_bounds<'tcx>( + dcx: DiagCtxtHandle<'tcx>, + bounds: hir::GenericBounds<'tcx>, + ) -> impl Iterator { + bounds.iter().flat_map(move |bound| match *bound { + rustc_hir::GenericBound::Trait(poly_trait_ref) => { + dcx.span_err( + poly_trait_ref.span, + "trait bounds aren't supported in forall where clauses", + ); + None + } + rustc_hir::GenericBound::Outlives(lifetime) => Some(lifetime), + rustc_hir::GenericBound::Use(_, span) => { + dcx.span_err(span, "use bounds aren't supported in forall where clauses"); + None + } + }) + } match predicate.kind { hir::WherePredicateKind::BoundPredicate(p) => { let bound_vars = self.tcx.late_bound_vars(predicate.hir_id); let ty = self.lower_ty(p.bounded_ty); - for bound in p.bounds { - match bound { - hir::GenericBound::Trait(poly_trait_ref) => { - self.dcx() - .span_err(poly_trait_ref.span, "trait bounds aren't supported yet"); - } - hir::GenericBound::Outlives(lifetime) => { - let region = self - .lowerer() - .lower_lifetime(lifetime, RegionInferReason::RegionPredicate); - let binder = ty::Binder::bind_with_vars( - ty::OutlivesClause(ty, region), - bound_vars, - ); - type_outlives.push(binder); - } - hir::GenericBound::Use(_, span) => { - self.dcx().span_err(*span, "use bounds aren't supported yet"); - } - } + for lifetime in outlives_bounds(self.dcx(), p.bounds) { + let region = + self.lowerer().lower_lifetime(lifetime, RegionInferReason::RegionPredicate); + let binder = + ty::Binder::bind_with_vars(ty::OutlivesClause(ty, region), bound_vars); + type_outlives.push(binder); } } - hir::WherePredicateKind::RegionPredicate(predicate) => { - let lhs = self - .lowerer() - .lower_lifetime(predicate.lifetime, RegionInferReason::RegionPredicate); - for bound in predicate.bounds { - match bound { - hir::GenericBound::Trait(poly_trait_ref) => { - self.dcx() - .span_err(poly_trait_ref.span, "trait bounds aren't supported yet"); - } - hir::GenericBound::Outlives(lifetime) => { - let rhs = self - .lowerer() - .lower_lifetime(lifetime, RegionInferReason::RegionPredicate); - region_outlives.push((lhs, rhs)); - } - hir::GenericBound::Use(_, span) => { - self.dcx().span_err(*span, "use bounds aren't supported yet"); - } - } + hir::WherePredicateKind::RegionPredicate(p) => { + let lhs = + self.lowerer().lower_lifetime(p.lifetime, RegionInferReason::RegionPredicate); + for lifetime in outlives_bounds(self.dcx(), p.bounds) { + let rhs = + self.lowerer().lower_lifetime(lifetime, RegionInferReason::RegionPredicate); + region_outlives.push(ty::OutlivesClause(lhs, rhs)); } } } diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs index 97629627ad556..42a334900f769 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs @@ -1,6 +1,8 @@ //@ compile-flags: -Zassumptions-on-binders #![feature(test_binder_constraints)] -#![expect(incomplete_features)] + +trait Trait<'a> {} +struct Struct<'a>(&'a u32); core::test_binder_constraints! { impl<'a, 'b> { @@ -27,8 +29,6 @@ core::test_binder_constraints! { } } -trait Trait<'a> {} - core::test_binder_constraints! { impl<'a> { dyn for<'b> Trait<'b>: 'a, @@ -47,6 +47,7 @@ core::test_binder_constraints! { impl<'a> { forall where T: 'a { //~^ ERROR only lifetime parameters can be used in this context + //~| ERROR the lhs of a forall where clause must be an alias, placeholder, or lifetime T: 'a, //~^ ERROR the lhs of a ty outlives must be a placeholder } @@ -74,4 +75,13 @@ core::test_binder_constraints! { } } +core::test_binder_constraints! { + impl<'a> { + forall<'b> where Struct<'a>: 'b { + //~^ ERROR the lhs of a forall where clause must be an alias, placeholder, or lifetime + //~| ERROR all implied bounds of clauses must themselves be included in the where clause of a forall + } + } +} + fn main() {} diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr index ab025b0e0b9d6..4513fd1fdb2c7 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr @@ -1,11 +1,11 @@ error: expected one of `!`, `(`, `+`, `::`, `:`, or `<`, found `{` - --> $DIR/test-infra-fails-properly.rs:15:20 + --> $DIR/test-infra-fails-properly.rs:17:20 | LL | forall { } | ^ expected one of `!`, `(`, `+`, `::`, `:`, or `<` error: expected one of `!`, `(`, `+`, `::`, `:`, or `<`, found `{` - --> $DIR/test-infra-fails-properly.rs:24:20 + --> $DIR/test-infra-fails-properly.rs:26:20 | LL | forall { } | ^ expected one of `!`, `(`, `+`, `::`, `:`, or `<` @@ -27,7 +27,7 @@ LL | forall where T: 'a { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: higher-ranked lifetime bound could not be satisfied - --> $DIR/test-infra-fails-properly.rs:7:9 + --> $DIR/test-infra-fails-properly.rs:9:9 | LL | 'a: 'b | ^^^^^^ @@ -39,10 +39,18 @@ LL | dyn for<'b> Trait<'b>: 'a, | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: it is a (dyn for<'b> Trait<'b> + 'static) - = note: and here it is `Debug`ged :3 dyn [Binder { value: Trait(Trait<'b>), bound_vars: [Region(BrNamed(DefId(0:11 ~ test_infra_fails_properly[2377]::{test_binder_constraints#1}::'b)))] }] + 'static + = note: and here it is `Debug`ged :3 dyn [Binder { value: Trait(Trait<'b>), bound_vars: [Region(BrNamed(DefId(0:15 ~ test_infra_fails_properly[2377]::{test_binder_constraints#1}::'b)))] }] + 'static + +error: the lhs of a forall where clause must be an alias, placeholder, or lifetime + --> $DIR/test-infra-fails-properly.rs:48:9 + | +LL | forall where T: 'a { + | ^^^^^^ + | + = note: the bad clause is {type error}: 'a error: the lhs of a ty outlives must be a placeholder - --> $DIR/test-infra-fails-properly.rs:50:13 + --> $DIR/test-infra-fails-properly.rs:51:13 | LL | T: 'a, | ^^^^^ @@ -51,33 +59,49 @@ LL | T: 'a, = note: and here it is `Debug`ged :3 {type error} error: forall expect clause failed - --> $DIR/test-infra-fails-properly.rs:63:17 + --> $DIR/test-infra-fails-properly.rs:64:17 | LL | 'b: 'c, | ^^^^^^ | note: constraint from here - --> $DIR/test-infra-fails-properly.rs:58:9 + --> $DIR/test-infra-fails-properly.rs:59:9 | LL | forall<'a> where 'b: 'a { | ^^^^^^ = note: expected: RegionOutlives( 'b/#0, 'c/#1, - $DIR/test-infra-fails-properly.rs:63:17: 63:23 (#0), + $DIR/test-infra-fails-properly.rs:64:17: 64:23 (#0), ) = note: actual: RegionOutlives( 'c/#1, 'static, - $DIR/test-infra-fails-properly.rs:58:9: 58:15 (#0), + $DIR/test-infra-fails-properly.rs:59:9: 59:15 (#0), ) error: bound type test binder constraint must be alias (it's a AliasTyOutlivesViaEnv) - --> $DIR/test-infra-fails-properly.rs:72:15 + --> $DIR/test-infra-fails-properly.rs:73:15 | LL | for<> T: 'a | ^ -error: aborting due to 9 previous errors +error: the lhs of a forall where clause must be an alias, placeholder, or lifetime + --> $DIR/test-infra-fails-properly.rs:80:9 + | +LL | forall<'b> where Struct<'a>: 'b { + | ^^^^^^ + | + = note: the bad clause is for<'b> Struct<'a>: 'b + +error: all implied bounds of clauses must themselves be included in the where clause of a forall + --> $DIR/test-infra-fails-properly.rs:80:9 + | +LL | forall<'b> where Struct<'a>: 'b { + | ^^^^^^ + | + = note: missing clause is for<'b> 'a: 'b + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/assumptions_on_binders/test-infra-works.rs b/tests/ui/assumptions_on_binders/test-infra-works.rs index d8d64d1aac255..2979478e76007 100644 --- a/tests/ui/assumptions_on_binders/test-infra-works.rs +++ b/tests/ui/assumptions_on_binders/test-infra-works.rs @@ -82,4 +82,12 @@ core::test_binder_constraints! { } } +core::test_binder_constraints! { + impl { + forall<'a> where TParam: 'a { }, + forall<'a> where TParam::Assoc: 'a { }, + forall<'a, T> where T: 'a { }, + } +} + fn main() {} From fa3bfde261f62d8a8acb3dd0da2133ca0e92164d Mon Sep 17 00:00:00 2001 From: xonx4l Date: Thu, 1 Oct 2026 16:44:49 +0530 Subject: [PATCH 05/24] fix build errors --- Cargo.lock | 1 + compiler/rustc_lint/Cargo.toml | 1 + compiler/rustc_lint/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5e57835c9cfef..5183eb88a437f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4334,6 +4334,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_hashes", "rustc_hir", "rustc_index", "rustc_infer", diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index a672f242449e4..5fc0b333eccad 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -14,6 +14,7 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 95033707cf110..9a91e14fbdcb0 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -238,7 +238,7 @@ late_lint_methods!( ImplTraitOvercaptures: ImplTraitOvercaptures, ImplicitAutorefs: ImplicitAutorefs, ImplicitProvenanceCasts: ImplicitProvenanceCasts, - ImproperCTypesLint: ImproperCTypesLint, + ImproperCTypesLint: ImproperCTypesLint::default(), ImproperGpuKernelLint: ImproperGpuKernelLint, InteriorMutableConsts: InteriorMutableConsts, InternalEqTraitMethodImpls: InternalEqTraitMethodImpls, From 7a1ec8e665a9691187de2964f11216883bfdc84d Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 4 Oct 2026 22:07:36 -0400 Subject: [PATCH 06/24] check is_indirect_first_projection when replacing in RefProp --- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- ...d_field_reborrow.ReferencePropagation.diff | 30 +++++++++++++++++ tests/mir-opt/reference_prop.rs | 32 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/mir-opt/reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 731060bd2c2b8..4bc47bc8890eb 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -335,7 +335,7 @@ fn compute_replacement<'tcx>( // // This also allows to detect cases where `target.local` is not replaceable, // and mark it as such. - if let &[PlaceElem::Deref] = &target.projection[..] { + if target.is_indirect_first_projection() { assert!(perform_opt); self.allowed_replacements.insert((target.local, loc)); place.local = target.local; diff --git a/tests/mir-opt/reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff b/tests/mir-opt/reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff new file mode 100644 index 0000000000000..6b3928451a2ed --- /dev/null +++ b/tests/mir-opt/reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff @@ -0,0 +1,30 @@ +- // MIR for `maybe_dead_field_reborrow` before ReferencePropagation ++ // MIR for `maybe_dead_field_reborrow` after ReferencePropagation + + fn maybe_dead_field_reborrow(_1: bool) -> i32 { + let mut _0: i32; + let mut _2: (i32, i32); + let mut _3: &mut (i32, i32); + let mut _4: &mut i32; + + bb0: { + StorageLive(_2); + _2 = (const 0_i32, const 0_i32); + _3 = &mut _2; + ((*_3).0: i32) = const 1_i32; +- _4 = &mut ((*_3).0: i32); + switchInt(copy _1) -> [1: bb1, otherwise: bb2]; + } + + bb1: { + StorageDead(_2); + goto -> bb2; + } + + bb2: { +- _0 = copy (*_4); ++ _0 = copy ((*_3).0: i32); + return; + } + } + diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index c4b63b6313c23..8220689baf1a4 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -776,6 +776,36 @@ fn maybe_dead(m: bool) { } } +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +fn maybe_dead_field_reborrow(m: bool) -> i32 { + // CHECK-LABEL: fn maybe_dead_field_reborrow( + // CHECK: [[r:_.*]] = &mut {{_.*}}; + // CHECK: ((*[[r]]).0: i32) = const 1_i32; + + use std::intrinsics::mir::*; + mir! { + let x: (i32, i32); + let r: &mut (i32, i32); + let r2: &mut i32; + { + StorageLive(x); + x = (0, 0); + r = &mut x; + (*r).0 = 1; + r2 = &mut (*r).0; + match m { true => bb1, _ => bb2 } + } + bb1 = { + StorageDead(x); + Goto(bb2) + } + bb2 = { + RET = *r2; + Return() + } + } +} + fn mut_raw_then_mut_shr() -> (i32, i32) { // CHECK-LABEL: fn mut_raw_then_mut_shr( // CHECK-NOT: (*{{_.*}}) @@ -875,6 +905,7 @@ fn main() { multiple_storage(); dominate_storage(); maybe_dead(true); + maybe_dead_field_reborrow(true); mut_raw_then_mut_shr(); unique_with_copies(); debuginfo(); @@ -889,6 +920,7 @@ fn main() { // EMIT_MIR reference_prop.multiple_storage.ReferencePropagation.diff // EMIT_MIR reference_prop.dominate_storage.ReferencePropagation.diff // EMIT_MIR reference_prop.maybe_dead.ReferencePropagation.diff +// EMIT_MIR reference_prop.maybe_dead_field_reborrow.ReferencePropagation.diff // EMIT_MIR reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff // EMIT_MIR reference_prop.unique_with_copies.ReferencePropagation.diff // EMIT_MIR reference_prop.debuginfo.ReferencePropagation.diff From 66c7ec68ddf67d63d729c6f7df5679b7458dccd8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 5 Oct 2026 18:15:41 +1100 Subject: [PATCH 07/24] Avoid `as_c_char_ptr` in debuginfo --- .../src/debuginfo/metadata.rs | 17 ++++++----- .../src/debuginfo/metadata/enums/mod.rs | 4 +-- .../src/debuginfo/metadata/enums/native.rs | 8 ++--- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 12 ++++---- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 30 +++++++++---------- 5 files changed, 36 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index a3bcce34566cb..e14cdeb1505d0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -32,7 +32,7 @@ use super::CodegenUnitDebugContext; use super::namespace::mangled_name_of_instance; use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name}; use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit}; -use crate::common::{AsCCharPtr, CodegenCx}; +use crate::common::CodegenCx; use crate::debuginfo::metadata::type_map::build_type_with_children; use crate::debuginfo::utils::{WidePtrKind, create_DIArray, wide_pointer_kind}; use crate::debuginfo::{DIBuilderExt, dwarf_const}; @@ -651,14 +651,14 @@ fn create_file<'ll>( unsafe { llvm::LLVMRustDIBuilderCreateFile( builder, - file_name.as_c_char_ptr(), + file_name.as_ptr(), file_name.len(), - directory.as_c_char_ptr(), + directory.as_ptr(), directory.len(), hash_kind, - hash_value.as_c_char_ptr(), + hash_value.as_ptr(), hash_value.len(), - source.map_or(ptr::null(), |x| x.as_c_char_ptr()), + source.map_or(ptr::null(), |x| x.as_ptr()), source.map_or(0, |x| x.len()), ) } @@ -949,20 +949,21 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( llvm::ChecksumKind::None, None, ); + let flags = c""; let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( debug_context.builder.as_ref(), dwarf_const::DW_LANG_Rust, compile_unit_file, - producer.as_c_char_ptr(), + producer.as_ptr(), producer.len(), tcx.sess.opts.optimize != config::OptLevel::No, - c"".as_ptr(), + flags.as_ptr(), 0, // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead // put the path supplied to `MCSplitDwarfFile` into the debug info of the final // output(s). - split_name.as_c_char_ptr(), + split_name.as_ptr(), split_name.len(), kind, 0, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 37f114fc5b09e..c2aa981582aaf 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -13,7 +13,7 @@ use rustc_span::{Span, Symbol, bug}; use super::type_map::{DINodeCreationResult, UniqueTypeId}; use super::{SmallVec, size_and_align_of}; -use crate::common::{AsCCharPtr, CodegenCx}; +use crate::common::CodegenCx; use crate::debuginfo::metadata::type_map::{self, Stub}; use crate::debuginfo::metadata::{ UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes, @@ -141,7 +141,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), containing_scope, - type_name.as_c_char_ptr(), + type_name.as_ptr(), type_name.len(), file_metadata, line_number, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index c0ecb14d21926..c9cac61a8bbe1 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_span::bug; use smallvec::smallvec; -use crate::common::{AsCCharPtr, CodegenCx}; +use crate::common::CodegenCx; use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId}; use crate::debuginfo::metadata::{ DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, create_member_type, @@ -284,7 +284,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( llvm::LLVMRustDIBuilderCreateVariantPart( DIB(cx), enum_type_di_node, - variant_part_name.as_c_char_ptr(), + variant_part_name.as_ptr(), variant_part_name.len(), file_metadata, line_number, @@ -293,7 +293,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( DIFlags::FlagZero, tag_member_di_node, create_DIArray(DIB(cx), &[]), - variant_part_unique_type_id_str.as_c_char_ptr(), + variant_part_unique_type_id_str.as_ptr(), variant_part_unique_type_id_str.len(), ) }, @@ -444,7 +444,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>( llvm::LLVMRustDIBuilderCreateVariantMemberType( DIB(cx), variant_part_di_node, - variant_member_info.variant_name.as_c_char_ptr(), + variant_member_info.variant_name.as_ptr(), variant_member_info.variant_name.len(), file_di_node, line_number, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 29448f147d103..99a54f1d74a62 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -34,7 +34,7 @@ use self::metadata::{ use self::namespace::mangled_name_of_instance; use self::utils::{DIB, create_DIArray, is_node_local_to_unit}; use crate::builder::Builder; -use crate::common::{AsCCharPtr, CodegenCx}; +use crate::common::CodegenCx; use crate::debuginfo::di_builder::DIBuilderBox; use crate::llvm::debuginfo::{ DIArray, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, @@ -197,9 +197,9 @@ impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { llvm::LLVMRustDIBuilderCreateMethod( DIB(self), containing_scope, - name.as_c_char_ptr(), + name.as_ptr(), name.len(), - linkage_name.as_c_char_ptr(), + linkage_name.as_ptr(), linkage_name.len(), file_metadata, loc.line, @@ -214,9 +214,9 @@ impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { llvm::LLVMRustDIBuilderCreateFunction( DIB(self), containing_scope, - name.as_c_char_ptr(), + name.as_ptr(), name.len(), - linkage_name.as_c_char_ptr(), + linkage_name.as_ptr(), linkage_name.len(), file_metadata, loc.line, @@ -716,7 +716,7 @@ impl<'ll> CodegenCx<'ll, '_> { llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(self), None, - name.as_c_char_ptr(), + name.as_ptr(), name.len(), actual_type_metadata, ) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4c7d60a0cbf67..1d2a902243c1b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2207,12 +2207,12 @@ unsafe extern "C" { Builder: &DIBuilder<'a>, Lang: c_uint, File: &'a DIFile, - Producer: *const c_char, + Producer: *const c_uchar, // See "PTR_LEN_STR". ProducerLen: size_t, isOptimized: bool, Flags: *const c_char, RuntimeVer: c_uint, - SplitName: *const c_char, + SplitName: *const c_uchar, // See "PTR_LEN_STR". SplitNameLen: size_t, kind: DebugEmissionKind, DWOId: u64, @@ -2224,14 +2224,14 @@ unsafe extern "C" { /// _requires_ a checksum, but we sometimes don't provide one. pub(crate) fn LLVMRustDIBuilderCreateFile<'a>( Builder: &DIBuilder<'a>, - Filename: *const c_char, + Filename: *const c_uchar, // See "PTR_LEN_STR". FilenameLen: size_t, - Directory: *const c_char, + Directory: *const c_uchar, // See "PTR_LEN_STR". DirectoryLen: size_t, CSKind: ChecksumKind, - Checksum: *const c_char, + Checksum: *const c_uchar, // See "PTR_LEN_STR". ChecksumLen: size_t, - Source: *const c_char, + Source: *const c_uchar, // See "PTR_LEN_STR". SourceLen: size_t, ) -> &'a DIFile; @@ -2240,9 +2240,9 @@ unsafe extern "C" { pub(crate) fn LLVMRustDIBuilderCreateFunction<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, - LinkageName: *const c_char, + LinkageName: *const c_uchar, // See "PTR_LEN_STR". LinkageNameLen: size_t, File: &'a DIFile, LineNo: c_uint, @@ -2259,9 +2259,9 @@ unsafe extern "C" { pub(crate) fn LLVMRustDIBuilderCreateMethod<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, - LinkageName: *const c_char, + LinkageName: *const c_uchar, // See "PTR_LEN_STR". LinkageNameLen: size_t, File: &'a DIFile, LineNo: c_uint, @@ -2275,7 +2275,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustDIBuilderCreateVariantMemberType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, File: &'a DIFile, LineNumber: c_uint, @@ -2291,7 +2291,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustDIBuilderCreateEnumerationType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, File: &'a DIFile, LineNumber: c_uint, @@ -2306,7 +2306,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustDIBuilderCreateVariantPart<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, File: &'a DIFile, LineNo: c_uint, @@ -2315,7 +2315,7 @@ unsafe extern "C" { Flags: DIFlags, Discriminator: Option<&'a DIDerivedType>, Elements: &'a DIArray, - UniqueId: *const c_char, + UniqueId: *const c_uchar, // See "PTR_LEN_STR". UniqueIdLen: size_t, ) -> &'a DIDerivedType; @@ -2323,7 +2323,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, Ty: &'a DIType, ) -> &'a DITemplateTypeParameter; From 891c24d7e2355fe73253226e8de81b8ea39aca80 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 5 Oct 2026 18:02:45 +1100 Subject: [PATCH 08/24] Avoid `as_c_char_ptr` in `declare.rs` --- compiler/rustc_codegen_llvm/src/declare.rs | 15 ++++----------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 8 ++++---- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 23f9fc93a4ba4..78bc5aba450aa 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -25,7 +25,6 @@ use tracing::debug; use crate::abi::FnAbiLlvmExt; use crate::attributes; -use crate::common::AsCCharPtr; use crate::context::{CodegenCx, GenericCx, SCx, SimpleCx}; use crate::llvm::AttributePlace::Function; use crate::llvm::{self, FromGeneric, Type, Value, Visibility}; @@ -43,8 +42,7 @@ pub(crate) fn declare_simple_fn<'ll>( ty: &'ll Type, ) -> &'ll Value { debug!("declare_simple_fn(name={:?}, ty={:?})", name, ty); - let llfn = - unsafe { llvm::LLVMGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty) }; + let llfn = unsafe { llvm::LLVMGetOrInsertFunction(cx.llmod, name.as_ptr(), name.len(), ty) }; llvm::SetFunctionCallConv(llfn, callconv); llvm::set_unnamed_address(llfn, unnamed); @@ -96,12 +94,7 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value { debug!("declare_global(name={:?})", name); unsafe { - llvm::LLVMRustGetOrInsertGlobal( - (**self).borrow().llmod, - name.as_c_char_ptr(), - name.len(), - ty, - ) + llvm::LLVMRustGetOrInsertGlobal((**self).borrow().llmod, name.as_ptr(), name.len(), ty) } } @@ -119,7 +112,7 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { unsafe { llvm::LLVMRustGetOrInsertGlobalInAddrspace( (**self).borrow().llmod, - name.as_c_char_ptr(), + name.as_ptr(), name.len(), ty, addr_space.0, @@ -261,7 +254,7 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { /// Gets declared value by name. pub(crate) fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); - unsafe { llvm::LLVMRustGetNamedValue(self.llmod(), name.as_c_char_ptr(), name.len()) } + unsafe { llvm::LLVMRustGetNamedValue(self.llmod(), name.as_ptr(), name.len()) } } /// Gets defined or externally defined (AvailableExternally linkage) value by diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 1d2a902243c1b..4349c9666040d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1127,7 +1127,7 @@ unsafe extern "C" { pub(crate) fn LLVMDeleteFunction(Fn: &Value); pub(crate) fn LLVMGetOrInsertFunction<'a>( M: &'a Module, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, FunctionTy: &'a Type, ) -> &'a Value; @@ -1992,20 +1992,20 @@ unsafe extern "C" { // Operations on global variables pub(crate) fn LLVMRustGetOrInsertGlobal<'a>( M: &'a Module, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, T: &'a Type, ) -> &'a Value; pub(crate) fn LLVMRustGetOrInsertGlobalInAddrspace<'a>( M: &'a Module, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, T: &'a Type, AddressSpace: c_uint, ) -> &'a Value; pub(crate) fn LLVMRustGetNamedValue( M: &Module, - Name: *const c_char, + Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: size_t, ) -> Option<&Value>; From ae54544c1134174fb308b49424f817a7bc9c7ed8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 5 Oct 2026 18:09:09 +1100 Subject: [PATCH 09/24] Avoid `as_c_char_ptr` in `write.rs` --- compiler/rustc_codegen_llvm/src/back/write.rs | 13 +++++-------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 6 +++--- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index a95f259545982..5bbe1c887a939 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -33,7 +33,6 @@ use crate::back::profiling::{ }; use crate::builder::SBuilder; use crate::builder::gpu_offload::scalar_width; -use crate::common::AsCCharPtr; use crate::context::SimpleCx; use crate::diagnostics::{ CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, ParseTargetMachineConfig, @@ -548,9 +547,7 @@ pub(crate) unsafe fn llvm_optimize( } else { None }; - let passes_after_enzyme_ptr = - passes_after_enzyme.map_or(std::ptr::null(), |s| s.as_c_char_ptr()); - let passes_after_enzyme_len = passes_after_enzyme.map_or(0, |s| s.len()); + let merge_functions; let unroll_loops; let vectorize_slp; @@ -788,11 +785,11 @@ pub(crate) unsafe fn llvm_optimize( llvm_selfprofiler, selfprofile_before_pass_callback, selfprofile_after_pass_callback, - passes_after_enzyme_ptr, - passes_after_enzyme_len, - extra_passes.as_c_char_ptr(), + passes_after_enzyme.map(|s| s.as_ptr()).unwrap_or(std::ptr::null()), + passes_after_enzyme.map(|s| s.len()).unwrap_or(0), + extra_passes.as_ptr(), extra_passes.len(), - llvm_plugins.as_c_char_ptr(), + llvm_plugins.as_ptr(), llvm_plugins.len(), ) }; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4349c9666040d..f9718834fb846 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2462,11 +2462,11 @@ unsafe extern "C" { llvm_selfprofiler: *mut c_void, begin_callback: SelfProfileBeforePassCallback, end_callback: SelfProfileAfterPassCallback, - PostEnzymePasses: *const c_char, + PostEnzymePasses: *const c_uchar, // See "PTR_LEN_STR". PostEnzymePassesLen: size_t, - ExtraPasses: *const c_char, + ExtraPasses: *const c_uchar, // See "PTR_LEN_STR". ExtraPassesLen: size_t, - LLVMPlugins: *const c_char, + LLVMPlugins: *const c_uchar, // See "PTR_LEN_STR". LLVMPluginsLen: size_t, ) -> LLVMRustResult; pub(crate) fn LLVMRustPrintModule( From 0f7320cc2385da083cad3636bb39572cee2b4e7f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 5 Oct 2026 11:05:13 +0200 Subject: [PATCH 10/24] Use target_family = "wasm" instead of target_arch = "wasm32" This slightly improves support for the WASM64 architecture. --- .../0028-sysroot_tests-Disable-long-running-tests.patch | 2 +- library/core/src/os/mod.rs | 4 ++-- library/coretests/benches/lib.rs | 4 ++-- library/coretests/tests/num/flt2dec/random.rs | 2 +- library/coretests/tests/slice.rs | 2 +- library/std/benches/time.rs | 4 ++-- library/std/src/net/tcp.rs | 6 +++--- library/std/src/os/fd/owned.rs | 6 +++--- library/std/src/os/fd/raw.rs | 2 +- library/std/src/os/mod.rs | 2 +- library/std/src/os/net/mod.rs | 2 +- library/std/src/os/unix/io/mod.rs | 2 +- library/std/tests/time.rs | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch index 853acab2773b5..e503acf8fee8c 100644 --- a/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch @@ -14,7 +14,7 @@ index 8402833..84592e0 100644 @@ -1619,7 +1619,7 @@ fn brute_force_rotate_test_1() { #[test] - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(all(target_family = "wasm", target_os = "unknown")))] -#[cfg_attr(miri, ignore)] // Miri is too slow +#[ignore] // Miri is too slow fn select_nth_unstable() { diff --git a/library/core/src/os/mod.rs b/library/core/src/os/mod.rs index 5ac2b637941ae..8d177dd3947c9 100644 --- a/library/core/src/os/mod.rs +++ b/library/core/src/os/mod.rs @@ -6,7 +6,7 @@ #[cfg(all( doc, any( - all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_family = "wasm", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) ))] @@ -17,7 +17,7 @@ pub mod darwin {} #[cfg(not(all( doc, any( - all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_family = "wasm", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) )))] diff --git a/library/coretests/benches/lib.rs b/library/coretests/benches/lib.rs index e8dc815a7dd0f..4815c3e44e1a1 100644 --- a/library/coretests/benches/lib.rs +++ b/library/coretests/benches/lib.rs @@ -1,5 +1,5 @@ -// wasm32 does not support benches (no time). -#![cfg(not(target_arch = "wasm32"))] +// wasm*-unknown-unknown does not support benches (no time). +#![cfg(all(target_family = "wasm", target_os = "unknown"))] // This is marked as `test = true` and hence picked up by `./x miri`, but that would be too slow. #![cfg(not(miri))] #![feature(flt2dec)] diff --git a/library/coretests/tests/num/flt2dec/random.rs b/library/coretests/tests/num/flt2dec/random.rs index e47aa6d37a804..b90386aee617c 100644 --- a/library/coretests/tests/num/flt2dec/random.rs +++ b/library/coretests/tests/num/flt2dec/random.rs @@ -1,4 +1,4 @@ -#![cfg(not(target_arch = "wasm32"))] +#![cfg(not(all(target_family = "wasm", target_os = "unknown")))] use core::num::imp::flt2dec; use std::mem::MaybeUninit; diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs index e570bff645af7..f7149abaf3f16 100644 --- a/library/coretests/tests/slice.rs +++ b/library/coretests/tests/slice.rs @@ -1679,7 +1679,7 @@ fn brute_force_rotate_test_1() { } #[test] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] #[cfg_attr(miri, ignore)] // Miri is too slow fn select_nth_unstable() { use core::cmp::Ordering::{Equal, Greater, Less}; diff --git a/library/std/benches/time.rs b/library/std/benches/time.rs index dfd886738f984..48d83672362b7 100644 --- a/library/std/benches/time.rs +++ b/library/std/benches/time.rs @@ -1,10 +1,10 @@ -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] use test::{Bencher, black_box}; macro_rules! bench_instant_threaded { ($bench_name:ident, $thread_count:expr) => { #[bench] - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(all(target_family = "wasm", target_os = "unknown")))] fn $bench_name(b: &mut Bencher) -> std::thread::Result<()> { use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 00f802e5d9155..e5c2522a837fb 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -913,9 +913,9 @@ impl TcpListener { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - // On WASM, `TcpStream` is uninhabited (as it's unsupported) and so - // the `a` variable here is technically unused. - #[cfg_attr(target_arch = "wasm32", allow(unused_variables))] + // On wasm*-unknown-unknown, `TcpStream` is uninhabited (as it's + // unsupported) and so the `a` variable here is technically unused. + #[cfg_attr(all(target_family = "wasm", target_os = "unknown"), allow(unused_variables))] self.0.accept().map(|(a, b)| (TcpStream(a), b)) } diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 87a8e20bad0d3..6c6f9b552c926 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -13,7 +13,7 @@ use crate::fs; use crate::marker::PhantomData; use crate::mem::ManuallyDrop; #[cfg(not(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_family = "wasm", not(target_os = "emscripten")), target_env = "sgx", target_os = "hermit", target_os = "trusty", @@ -105,7 +105,7 @@ impl BorrowedFd<'_> { /// Creates a new `OwnedFd` instance that shares the same underlying file /// description as the existing `BorrowedFd` instance. #[cfg(not(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_family = "wasm", not(target_os = "emscripten")), target_os = "hermit", target_os = "trusty", target_os = "motor" @@ -133,7 +133,7 @@ impl BorrowedFd<'_> { /// Creates a new `OwnedFd` instance that shares the same underlying file /// description as the existing `BorrowedFd` instance. #[cfg(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_family = "wasm", not(target_os = "emscripten")), target_os = "hermit", target_os = "trusty" ))] diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index a8d981520efd2..4d7b6a3e5fb53 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -17,7 +17,7 @@ use crate::io; use crate::os::hermit::io::OwnedFd; #[cfg(all(not(target_os = "hermit"), not(target_os = "motor")))] use crate::os::raw; -#[cfg(all(doc, not(any(target_arch = "wasm32", target_env = "sgx", target_os = "l4re"))))] +#[cfg(all(doc, not(any(target_family = "wasm", target_env = "sgx", target_os = "l4re"))))] use crate::os::unix::io::AsFd; #[cfg(unix)] use crate::os::unix::io::OwnedFd; diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 8068f92bcc93c..f95c6ac8dd76d 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -16,7 +16,7 @@ pub mod raw; #[cfg(doc)] cfg_select! { any( - all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_family = "wasm", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) => { #[unstable(issue = "none", feature = "std_internals")] diff --git a/library/std/src/os/net/mod.rs b/library/std/src/os/net/mod.rs index 47e69b3a260dc..cbde585c8d79f 100644 --- a/library/std/src/os/net/mod.rs +++ b/library/std/src/os/net/mod.rs @@ -5,7 +5,7 @@ #[cfg(not(all( doc, any( - all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_family = "wasm", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) )))] diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 4afb8ffa71017..099bdd35439a1 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -216,7 +216,7 @@ fn replace_stdio_fd(this: BorrowedFd<'_>, other: OwnedFd) -> io::Result<()> { .map(|_| ()) } not(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_family = "wasm", not(target_os = "emscripten")), target_os = "hermit", target_os = "trusty", target_os = "motor" diff --git a/library/std/tests/time.rs b/library/std/tests/time.rs index 6d8b4cbfd094f..4d47b068ab87a 100644 --- a/library/std/tests/time.rs +++ b/library/std/tests/time.rs @@ -29,7 +29,7 @@ fn instant_monotonic() { } #[test] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] fn instant_monotonic_concurrent() -> std::thread::Result<()> { let threads: Vec<_> = (0..8) .map(|_| { From 54bdb68955ecabe72cd5e13cb527c19967fab9eb Mon Sep 17 00:00:00 2001 From: Jamesbarford Date: Mon, 5 Oct 2026 13:40:10 +0000 Subject: [PATCH 11/24] Add `has_reliable_f16b` for Arm --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index a582e897eef9c..ea91756b9068a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -399,7 +399,7 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { // This is similar to , however // does not work until LLVM 23 on Windows. (Arch::Arm64EC, _) => major >= 23, - (Arch::AArch64, _) => true, + (Arch::AArch64 | Arch::Arm, _) => true, // FIXME(f16b) until // is resolved the below do not have a reliable `f16b`, on a widening // path a call to `__truncsfbf2` is emitted. Or when using architectural From 9837aeb52e90b63fa147ba59db07dd0bf957baf5 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 5 Oct 2026 19:01:29 +0200 Subject: [PATCH 12/24] Update books --- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/nomicon b/src/doc/nomicon index 5791ca9f5d671..46fc44214afcd 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 5791ca9f5d671328af7a8fe87b42ca90c7211d28 +Subproject commit 46fc44214afcd159be175c8ee62887cad04f615d diff --git a/src/doc/reference b/src/doc/reference index 4245282b97496..a286e1ecb8ce1 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 4245282b97496585e73862b966d639cbb553bd6c +Subproject commit a286e1ecb8ce193d50056e4bb042eea9b23876ef diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index af5ef7024e885..dcc14f912bf87 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit af5ef7024e88587aa3be244422f6365e86c50e85 +Subproject commit dcc14f912bf8790792a2df082eddc82ab2539229 From 54a6d2e4c750c76885dc444ec5eb97a30e85a695 Mon Sep 17 00:00:00 2001 From: xonx4l Date: Mon, 5 Oct 2026 23:29:44 +0530 Subject: [PATCH 13/24] factor out as check_ffi_type method --- .../rustc_lint/src/types/improper_ctypes.rs | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 2d42e9fdd05da..04b381261e428 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -149,6 +149,29 @@ impl<'tcx> ImproperCTypesLint { fn cache_key(cx: &LateContext<'tcx>, ty: Ty<'tcx>, flags: RootUseFlags) -> (Hash128, u8) { (cx.tcx.type_id_hash(ty), flags.bits()) } + + fn check_ffi_type( + &self, + cx: &LateContext<'tcx>, + ty: Ty<'tcx>, + state: VisitorState, + span: Span, + mode: CItemKind, + check: impl FnOnce() -> FfiResult<'tcx>, + ) { + let key = Self::cache_key(cx, ty, state.root_use_flags); + if self.known_safe.borrow().contains(&key) { + return; + } + + let ffi_res = check(); + + if matches!(ffi_res, FfiResult::FfiSafe) { + self.known_safe.borrow_mut().insert(key); + } + + self.process_ffi_result(cx, span, ffi_res, mode); + } } impl_lint_pass!(ImproperCTypesLint => [ @@ -1123,16 +1146,10 @@ impl<'tcx> ImproperCTypesLint { fn check_foreign_static(&mut self, cx: &LateContext<'tcx>, id: hir::OwnerId, span: Span) { let ty = cx.tcx.type_of(id).instantiate_identity(); let state = VisitorState::static_entry_point(); - let key = Self::cache_key(cx, ty.skip_norm_wip(), state.root_use_flags); - if self.known_safe.borrow().contains(&key) { - return; - } - let mut visitor = ImproperCTypesVisitor::new(cx, ty, CItemKind::Declaration); - let ffi_res = visitor.check_type(state, ty); - if matches!(ffi_res, FfiResult::FfiSafe) { - self.known_safe.borrow_mut().insert(key); - } - self.process_ffi_result(cx, span, ffi_res, CItemKind::Declaration); + self.check_ffi_type(cx, ty.skip_norm_wip(), state, span, CItemKind::Declaration, || { + let mut visitor = ImproperCTypesVisitor::new(cx, ty, CItemKind::Declaration); + visitor.check_type(state, ty) + }); } /// Check if a function's argument types and result type are "ffi-safe". @@ -1148,31 +1165,20 @@ impl<'tcx> ImproperCTypesLint { for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { let state = VisitorState::fn_entry_point(fn_mode, FnPos::Arg); - let key = Self::cache_key(cx, *input_ty, state.root_use_flags); - if self.known_safe.borrow().contains(&key) { - continue; - } - let input_ty = Unnormalized::new_wip(*input_ty); - let mut visitor = ImproperCTypesVisitor::new(cx, input_ty, fn_mode); - let ffi_res = visitor.check_type(state, input_ty); - if matches!(ffi_res, FfiResult::FfiSafe) { - self.known_safe.borrow_mut().insert(key); - } - self.process_ffi_result(cx, input_hir.span, ffi_res, fn_mode); + self.check_ffi_type(cx, *input_ty, state, input_hir.span, fn_mode, || { + let input_ty = Unnormalized::new_wip(*input_ty); + let mut visitor = ImproperCTypesVisitor::new(cx, input_ty, fn_mode); + visitor.check_type(state, input_ty) + }); } if let hir::FnRetTy::Return(ret_hir) = decl.output { let state = VisitorState::fn_entry_point(fn_mode, FnPos::Ret); - let key = Self::cache_key(cx, sig.output(), state.root_use_flags); - if !self.known_safe.borrow().contains(&key) { + self.check_ffi_type(cx, sig.output(), state, ret_hir.span, fn_mode, || { let output_ty = Unnormalized::new_wip(sig.output()); let mut visitor = ImproperCTypesVisitor::new(cx, output_ty, fn_mode); - let ffi_res = visitor.check_type(state, output_ty); - if matches!(ffi_res, FfiResult::FfiSafe) { - self.known_safe.borrow_mut().insert(key); - } - self.process_ffi_result(cx, ret_hir.span, ffi_res, fn_mode); - } + visitor.check_type(state, output_ty) + }); } } From 9de9ceb55138da485f465e7d5f6d23b73fda9528 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 4 Oct 2026 22:04:59 +0200 Subject: [PATCH 14/24] Move more tests around in `rustdoc-html` --- tests/rustdoc-html/README.md | 5 +++++ .../decl-line-wrapping-empty-arg-list.decl.html | 0 .../{ => display}/decl-line-wrapping-empty-arg-list.rs | 0 .../{ => display}/decl-trailing-whitespace.declaration.html | 0 tests/rustdoc-html/{ => display}/decl-trailing-whitespace.rs | 0 .../extremely_long_typename.extremely_long_typename.html | 0 tests/rustdoc-html/{ => display}/extremely_long_typename.rs | 0 .../{ => display}/item-desc-list-at-start.item-table.html | 0 tests/rustdoc-html/{ => display}/item-desc-list-at-start.rs | 0 tests/rustdoc-html/{ => display}/where.SWhere_Echo_impl.html | 0 .../{ => display}/where.SWhere_Simd_item-decl.html | 0 .../{ => display}/where.SWhere_TraitWhere_item-decl.html | 0 tests/rustdoc-html/{ => display}/where.alpha_trait_decl.html | 0 tests/rustdoc-html/{ => display}/where.bravo_trait_decl.html | 0 tests/rustdoc-html/{ => display}/where.charlie_fn_decl.html | 0 .../{ => display}/where.golf_type_alias_decl.html | 0 tests/rustdoc-html/{ => display}/where.rs | 0 .../{ => display}/whitespace-after-where-clause.enum.html | 0 .../{ => display}/whitespace-after-where-clause.enum2.html | 0 .../{ => display}/whitespace-after-where-clause.rs | 0 .../{ => display}/whitespace-after-where-clause.struct.html | 0 .../{ => display}/whitespace-after-where-clause.struct2.html | 0 .../{ => display}/whitespace-after-where-clause.trait.html | 0 .../{ => display}/whitespace-after-where-clause.trait2.html | 0 .../{ => display}/whitespace-after-where-clause.union.html | 0 .../{ => display}/whitespace-after-where-clause.union2.html | 0 tests/rustdoc-html/{ => extern}/auxiliary/rustdoc-ffi.rs | 0 tests/rustdoc-html/{ => extern}/ffi.rs | 0 tests/rustdoc-html/{ => extern}/foreigntype.rs | 0 tests/rustdoc-html/{ => hidden}/doc-hidden-crate.rs | 0 tests/rustdoc-html/reexport/auxiliary/pub-extern-crate.rs | 2 ++ .../rustdoc-html/{ => reexport}/auxiliary/reexp-stripped.rs | 0 .../duplicate-reexports-section-150211.rs | 0 tests/rustdoc-html/{ => reexport}/hidden-methods.rs | 0 tests/rustdoc-html/{ => reexport}/redirect.rs | 0 tests/{rustdoc-html => rustdoc-ui/lints}/cap-lints.rs | 4 +++- 36 files changed, 10 insertions(+), 1 deletion(-) rename tests/rustdoc-html/{ => display}/decl-line-wrapping-empty-arg-list.decl.html (100%) rename tests/rustdoc-html/{ => display}/decl-line-wrapping-empty-arg-list.rs (100%) rename tests/rustdoc-html/{ => display}/decl-trailing-whitespace.declaration.html (100%) rename tests/rustdoc-html/{ => display}/decl-trailing-whitespace.rs (100%) rename tests/rustdoc-html/{ => display}/extremely_long_typename.extremely_long_typename.html (100%) rename tests/rustdoc-html/{ => display}/extremely_long_typename.rs (100%) rename tests/rustdoc-html/{ => display}/item-desc-list-at-start.item-table.html (100%) rename tests/rustdoc-html/{ => display}/item-desc-list-at-start.rs (100%) rename tests/rustdoc-html/{ => display}/where.SWhere_Echo_impl.html (100%) rename tests/rustdoc-html/{ => display}/where.SWhere_Simd_item-decl.html (100%) rename tests/rustdoc-html/{ => display}/where.SWhere_TraitWhere_item-decl.html (100%) rename tests/rustdoc-html/{ => display}/where.alpha_trait_decl.html (100%) rename tests/rustdoc-html/{ => display}/where.bravo_trait_decl.html (100%) rename tests/rustdoc-html/{ => display}/where.charlie_fn_decl.html (100%) rename tests/rustdoc-html/{ => display}/where.golf_type_alias_decl.html (100%) rename tests/rustdoc-html/{ => display}/where.rs (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.enum.html (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.enum2.html (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.rs (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.struct.html (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.struct2.html (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.trait.html (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.trait2.html (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.union.html (100%) rename tests/rustdoc-html/{ => display}/whitespace-after-where-clause.union2.html (100%) rename tests/rustdoc-html/{ => extern}/auxiliary/rustdoc-ffi.rs (100%) rename tests/rustdoc-html/{ => extern}/ffi.rs (100%) rename tests/rustdoc-html/{ => extern}/foreigntype.rs (100%) rename tests/rustdoc-html/{ => hidden}/doc-hidden-crate.rs (100%) create mode 100644 tests/rustdoc-html/reexport/auxiliary/pub-extern-crate.rs rename tests/rustdoc-html/{ => reexport}/auxiliary/reexp-stripped.rs (100%) rename tests/rustdoc-html/{extern => reexport}/duplicate-reexports-section-150211.rs (100%) rename tests/rustdoc-html/{ => reexport}/hidden-methods.rs (100%) rename tests/rustdoc-html/{ => reexport}/redirect.rs (100%) rename tests/{rustdoc-html => rustdoc-ui/lints}/cap-lints.rs (84%) diff --git a/tests/rustdoc-html/README.md b/tests/rustdoc-html/README.md index 4acb1d54bbb89..055c03b1eed35 100644 --- a/tests/rustdoc-html/README.md +++ b/tests/rustdoc-html/README.md @@ -48,6 +48,11 @@ conflicts, in particular for simpler crate names). Contains tests to check the display of items implementing the `Deref` and/or `DerefMut` traits. +## `tests/rustdoc-html/display` + +Contains tests checking how items are displayed in the docs. Ensuring that methods with a lot +of arguments or with a lot of generics are correctly split between multiple lines for example. + ## `tests/rustdoc-html/doc-cfg` Contains tests to check the rustdoc `doc_cfg` feature. diff --git a/tests/rustdoc-html/decl-line-wrapping-empty-arg-list.decl.html b/tests/rustdoc-html/display/decl-line-wrapping-empty-arg-list.decl.html similarity index 100% rename from tests/rustdoc-html/decl-line-wrapping-empty-arg-list.decl.html rename to tests/rustdoc-html/display/decl-line-wrapping-empty-arg-list.decl.html diff --git a/tests/rustdoc-html/decl-line-wrapping-empty-arg-list.rs b/tests/rustdoc-html/display/decl-line-wrapping-empty-arg-list.rs similarity index 100% rename from tests/rustdoc-html/decl-line-wrapping-empty-arg-list.rs rename to tests/rustdoc-html/display/decl-line-wrapping-empty-arg-list.rs diff --git a/tests/rustdoc-html/decl-trailing-whitespace.declaration.html b/tests/rustdoc-html/display/decl-trailing-whitespace.declaration.html similarity index 100% rename from tests/rustdoc-html/decl-trailing-whitespace.declaration.html rename to tests/rustdoc-html/display/decl-trailing-whitespace.declaration.html diff --git a/tests/rustdoc-html/decl-trailing-whitespace.rs b/tests/rustdoc-html/display/decl-trailing-whitespace.rs similarity index 100% rename from tests/rustdoc-html/decl-trailing-whitespace.rs rename to tests/rustdoc-html/display/decl-trailing-whitespace.rs diff --git a/tests/rustdoc-html/extremely_long_typename.extremely_long_typename.html b/tests/rustdoc-html/display/extremely_long_typename.extremely_long_typename.html similarity index 100% rename from tests/rustdoc-html/extremely_long_typename.extremely_long_typename.html rename to tests/rustdoc-html/display/extremely_long_typename.extremely_long_typename.html diff --git a/tests/rustdoc-html/extremely_long_typename.rs b/tests/rustdoc-html/display/extremely_long_typename.rs similarity index 100% rename from tests/rustdoc-html/extremely_long_typename.rs rename to tests/rustdoc-html/display/extremely_long_typename.rs diff --git a/tests/rustdoc-html/item-desc-list-at-start.item-table.html b/tests/rustdoc-html/display/item-desc-list-at-start.item-table.html similarity index 100% rename from tests/rustdoc-html/item-desc-list-at-start.item-table.html rename to tests/rustdoc-html/display/item-desc-list-at-start.item-table.html diff --git a/tests/rustdoc-html/item-desc-list-at-start.rs b/tests/rustdoc-html/display/item-desc-list-at-start.rs similarity index 100% rename from tests/rustdoc-html/item-desc-list-at-start.rs rename to tests/rustdoc-html/display/item-desc-list-at-start.rs diff --git a/tests/rustdoc-html/where.SWhere_Echo_impl.html b/tests/rustdoc-html/display/where.SWhere_Echo_impl.html similarity index 100% rename from tests/rustdoc-html/where.SWhere_Echo_impl.html rename to tests/rustdoc-html/display/where.SWhere_Echo_impl.html diff --git a/tests/rustdoc-html/where.SWhere_Simd_item-decl.html b/tests/rustdoc-html/display/where.SWhere_Simd_item-decl.html similarity index 100% rename from tests/rustdoc-html/where.SWhere_Simd_item-decl.html rename to tests/rustdoc-html/display/where.SWhere_Simd_item-decl.html diff --git a/tests/rustdoc-html/where.SWhere_TraitWhere_item-decl.html b/tests/rustdoc-html/display/where.SWhere_TraitWhere_item-decl.html similarity index 100% rename from tests/rustdoc-html/where.SWhere_TraitWhere_item-decl.html rename to tests/rustdoc-html/display/where.SWhere_TraitWhere_item-decl.html diff --git a/tests/rustdoc-html/where.alpha_trait_decl.html b/tests/rustdoc-html/display/where.alpha_trait_decl.html similarity index 100% rename from tests/rustdoc-html/where.alpha_trait_decl.html rename to tests/rustdoc-html/display/where.alpha_trait_decl.html diff --git a/tests/rustdoc-html/where.bravo_trait_decl.html b/tests/rustdoc-html/display/where.bravo_trait_decl.html similarity index 100% rename from tests/rustdoc-html/where.bravo_trait_decl.html rename to tests/rustdoc-html/display/where.bravo_trait_decl.html diff --git a/tests/rustdoc-html/where.charlie_fn_decl.html b/tests/rustdoc-html/display/where.charlie_fn_decl.html similarity index 100% rename from tests/rustdoc-html/where.charlie_fn_decl.html rename to tests/rustdoc-html/display/where.charlie_fn_decl.html diff --git a/tests/rustdoc-html/where.golf_type_alias_decl.html b/tests/rustdoc-html/display/where.golf_type_alias_decl.html similarity index 100% rename from tests/rustdoc-html/where.golf_type_alias_decl.html rename to tests/rustdoc-html/display/where.golf_type_alias_decl.html diff --git a/tests/rustdoc-html/where.rs b/tests/rustdoc-html/display/where.rs similarity index 100% rename from tests/rustdoc-html/where.rs rename to tests/rustdoc-html/display/where.rs diff --git a/tests/rustdoc-html/whitespace-after-where-clause.enum.html b/tests/rustdoc-html/display/whitespace-after-where-clause.enum.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.enum.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.enum.html diff --git a/tests/rustdoc-html/whitespace-after-where-clause.enum2.html b/tests/rustdoc-html/display/whitespace-after-where-clause.enum2.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.enum2.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.enum2.html diff --git a/tests/rustdoc-html/whitespace-after-where-clause.rs b/tests/rustdoc-html/display/whitespace-after-where-clause.rs similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.rs rename to tests/rustdoc-html/display/whitespace-after-where-clause.rs diff --git a/tests/rustdoc-html/whitespace-after-where-clause.struct.html b/tests/rustdoc-html/display/whitespace-after-where-clause.struct.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.struct.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.struct.html diff --git a/tests/rustdoc-html/whitespace-after-where-clause.struct2.html b/tests/rustdoc-html/display/whitespace-after-where-clause.struct2.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.struct2.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.struct2.html diff --git a/tests/rustdoc-html/whitespace-after-where-clause.trait.html b/tests/rustdoc-html/display/whitespace-after-where-clause.trait.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.trait.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.trait.html diff --git a/tests/rustdoc-html/whitespace-after-where-clause.trait2.html b/tests/rustdoc-html/display/whitespace-after-where-clause.trait2.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.trait2.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.trait2.html diff --git a/tests/rustdoc-html/whitespace-after-where-clause.union.html b/tests/rustdoc-html/display/whitespace-after-where-clause.union.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.union.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.union.html diff --git a/tests/rustdoc-html/whitespace-after-where-clause.union2.html b/tests/rustdoc-html/display/whitespace-after-where-clause.union2.html similarity index 100% rename from tests/rustdoc-html/whitespace-after-where-clause.union2.html rename to tests/rustdoc-html/display/whitespace-after-where-clause.union2.html diff --git a/tests/rustdoc-html/auxiliary/rustdoc-ffi.rs b/tests/rustdoc-html/extern/auxiliary/rustdoc-ffi.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/rustdoc-ffi.rs rename to tests/rustdoc-html/extern/auxiliary/rustdoc-ffi.rs diff --git a/tests/rustdoc-html/ffi.rs b/tests/rustdoc-html/extern/ffi.rs similarity index 100% rename from tests/rustdoc-html/ffi.rs rename to tests/rustdoc-html/extern/ffi.rs diff --git a/tests/rustdoc-html/foreigntype.rs b/tests/rustdoc-html/extern/foreigntype.rs similarity index 100% rename from tests/rustdoc-html/foreigntype.rs rename to tests/rustdoc-html/extern/foreigntype.rs diff --git a/tests/rustdoc-html/doc-hidden-crate.rs b/tests/rustdoc-html/hidden/doc-hidden-crate.rs similarity index 100% rename from tests/rustdoc-html/doc-hidden-crate.rs rename to tests/rustdoc-html/hidden/doc-hidden-crate.rs diff --git a/tests/rustdoc-html/reexport/auxiliary/pub-extern-crate.rs b/tests/rustdoc-html/reexport/auxiliary/pub-extern-crate.rs new file mode 100644 index 0000000000000..8c89c8d6c76c5 --- /dev/null +++ b/tests/rustdoc-html/reexport/auxiliary/pub-extern-crate.rs @@ -0,0 +1,2 @@ +#![crate_name = "inner"] +pub struct SomeStruct; diff --git a/tests/rustdoc-html/auxiliary/reexp-stripped.rs b/tests/rustdoc-html/reexport/auxiliary/reexp-stripped.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/reexp-stripped.rs rename to tests/rustdoc-html/reexport/auxiliary/reexp-stripped.rs diff --git a/tests/rustdoc-html/extern/duplicate-reexports-section-150211.rs b/tests/rustdoc-html/reexport/duplicate-reexports-section-150211.rs similarity index 100% rename from tests/rustdoc-html/extern/duplicate-reexports-section-150211.rs rename to tests/rustdoc-html/reexport/duplicate-reexports-section-150211.rs diff --git a/tests/rustdoc-html/hidden-methods.rs b/tests/rustdoc-html/reexport/hidden-methods.rs similarity index 100% rename from tests/rustdoc-html/hidden-methods.rs rename to tests/rustdoc-html/reexport/hidden-methods.rs diff --git a/tests/rustdoc-html/redirect.rs b/tests/rustdoc-html/reexport/redirect.rs similarity index 100% rename from tests/rustdoc-html/redirect.rs rename to tests/rustdoc-html/reexport/redirect.rs diff --git a/tests/rustdoc-html/cap-lints.rs b/tests/rustdoc-ui/lints/cap-lints.rs similarity index 84% rename from tests/rustdoc-html/cap-lints.rs rename to tests/rustdoc-ui/lints/cap-lints.rs index 30f9be0424c6a..692a63f2f7332 100644 --- a/tests/rustdoc-html/cap-lints.rs +++ b/tests/rustdoc-ui/lints/cap-lints.rs @@ -1,9 +1,11 @@ // This should fail a normal compile due to non_camel_case_types, // It should pass a doc-compile as it only needs to type-check and // therefore should not concern itself with the lints. + +//@ check-pass + #[deny(warnings)] -//@ has cap_lints/struct.Foo.html //* 'Foo' pub struct Foo { field: i32, } From 78aa1c866b14f20c334fd3b18818b775779c0a7a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 4 Oct 2026 22:11:50 +0200 Subject: [PATCH 15/24] Replace some `!has` checks in `rustdoc-html` test --- tests/rustdoc-html/reexport/hidden-methods.rs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/rustdoc-html/reexport/hidden-methods.rs b/tests/rustdoc-html/reexport/hidden-methods.rs index ed9c1ee1aac29..4be81da1cf775 100644 --- a/tests/rustdoc-html/reexport/hidden-methods.rs +++ b/tests/rustdoc-html/reexport/hidden-methods.rs @@ -17,13 +17,24 @@ pub mod hidden { } //@ has foo/struct.Foo.html -//@ !hasraw - 'Methods' -//@ !has - '//code' 'impl Foo' -//@ !hasraw - 'this_should_be_hidden' +// Only `not_hidden` should be present. +//@ count - '//*[@id="implementations-list"]//*[@class="method"]' 1 +//@ has - '//*[@id="implementations-list"]//*[@class="method"]' 'pub fn not_hidden' +//@ count - '//*[@id="rustdoc-toc"]/*[@class="block method"]//a' 1 +//@ has - '//*[@id="rustdoc-toc"]/*[@class="block method"]//a' 'not_hidden' pub use hidden::Foo; +impl Foo { + pub fn not_hidden() {} +} + //@ has foo/struct.Bar.html -//@ !hasraw - 'Methods' -//@ !has - '//code' 'impl Bar' -//@ !hasraw - 'this_should_be_hidden' +//@ count - '//*[@id="implementations-list"]//*[@class="method"]' 1 +//@ has - '//*[@id="implementations-list"]//*[@class="method"]' 'pub fn not_hidden' +//@ count - '//*[@id="rustdoc-toc"]/*[@class="block method"]//a' 1 +//@ has - '//*[@id="rustdoc-toc"]/*[@class="block method"]//a' 'not_hidden' pub use hidden::Bar; + +impl Bar { + pub fn not_hidden() {} +} From 60afb4191406c16a0094ddc78b062a4e00a390d0 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 5 Oct 2026 17:48:59 -0700 Subject: [PATCH 16/24] ci: update to PowerShell 7.6.6 --- src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile b/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile index e7191aa31c47b..3552f4bc30e53 100644 --- a/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile +++ b/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile @@ -34,9 +34,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* # Install powershell (universal package) so we can test x.ps1 on Linux -# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep. -RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ - dpkg --ignore-depends=libicu72 -i powershell.deb && \ +RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.6.6/powershell_7.6.6-1.deb_amd64.deb" > powershell.deb && \ + dpkg -i powershell.deb && \ rm -f powershell.deb COPY scripts/sccache.sh /scripts/ From f57e16de8b4f5c79fe2c31a5c770b5debfade633 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Mon, 21 Sep 2026 01:52:44 -0500 Subject: [PATCH 17/24] add `required_python_version` to jobs --- src/ci/citool/src/jobs.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index e371105ebdb01..b94f12a37cc77 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -31,6 +31,10 @@ pub struct Job { pub doc_url: Option, /// Whether the job is executed on AWS CodeBuild. pub codebuild: Option, + /// Which Python version (if any) is required. On Windows, this is typically required to run + /// LLDB. + #[serde(default)] + pub required_python_version: Option, } impl Job { @@ -167,6 +171,7 @@ fn validate_job_database(db: &JobDatabase) -> anyhow::Result<()> { free_disk, doc_url, codebuild, + required_python_version, // Carve-out configs allowed to be different. env: _, @@ -179,6 +184,7 @@ fn validate_job_database(db: &JobDatabase) -> anyhow::Result<()> { && *free_disk == auto_job.free_disk && *doc_url == auto_job.doc_url && *codebuild == auto_job.codebuild + && *required_python_version == auto_job.required_python_version { Ok(()) } else { @@ -244,6 +250,8 @@ struct GithubActionsJob { doc_url: Option, #[serde(skip_serializing_if = "Option::is_none")] codebuild: Option, + #[serde(skip_serializing_if = "Option::is_none")] + required_python_version: Option, } /// Replace GitHub context variables with environment variables in job configs. @@ -375,6 +383,7 @@ fn calculate_jobs( free_disk: job.free_disk, doc_url: job.doc_url, codebuild: job.codebuild, + required_python_version: job.required_python_version, } }) .collect(); From 9109556143d8a781d31621c927a6391746ef2039 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Tue, 6 Oct 2026 00:54:19 -0500 Subject: [PATCH 18/24] run LLDB debuginfo tests on Windows CI --- .github/workflows/ci.yml | 9 +++++++++ src/ci/github-actions/jobs.yml | 3 +++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0f896724ae56..0c5c5fe46d394 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,6 +190,15 @@ jobs: - name: install ninja run: src/ci/scripts/install-ninja.sh + - name: install required Python version + # LLDB on Windows requires the same Python version it was built against to be the first + # discoverable Python in $env:PATH. Only install if we're actually running Windows tests + # that use LLDB + if: ${{ startsWith(matrix.os, 'windows') && matrix.required_python_version}} + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: ${{ matrix.required_python_version }} + - name: enable ipv6 on Docker # Don't run on codebuild because systemctl is not available if: ${{ !matrix.codebuild }} diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 57432451b9798..05e17c335aaf0 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -670,9 +670,12 @@ auto: # x86_64-msvc is split into two jobs to run tests in parallel. - name: test-x86_64-msvc-1 + # required to run LLDB 22 + required_python_version: '3.11' env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-sanitizers --enable-profiler SCRIPT: make ci-msvc-py + LLDB_PATH: ./citools/clang-rust/bin/lldb.exe <<: *job-windows - name: test-x86_64-msvc-2 From e1a95eb0a930ec95cdd1802a677ed8ffbf226b90 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 6 Oct 2026 07:27:13 +0000 Subject: [PATCH 19/24] use the type name instead of `Self` in constructor paths again --- .../src/deriving/clone.rs | 9 +-- .../src/deriving/debug.rs | 2 +- .../src/deriving/default.rs | 11 +-- .../rustc_builtin_macros/src/deriving/eq.rs | 2 +- .../rustc_builtin_macros/src/deriving/from.rs | 2 +- .../src/deriving/generic/mod.rs | 77 +++++++++++++++---- .../rustc_builtin_macros/src/deriving/hash.rs | 2 +- .../src/deriving/partial_eq.rs | 2 +- .../src/deriving/partial_ord.rs | 2 +- .../derives/attr-macro-changes-type-kind.rs | 15 ++++ tests/ui/derives/auxiliary/struct-to-enum.rs | 18 +++++ tests/ui/derives/deriving-all-codegen.stdout | 56 ++++++++------ tests/ui/stats/macro-stats.stderr | 4 +- 13 files changed, 145 insertions(+), 57 deletions(-) create mode 100644 tests/ui/derives/attr-macro-changes-type-kind.rs create mode 100644 tests/ui/derives/auxiliary/struct-to-enum.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 370c0ceeda909..5c2c3052d1d51 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -147,7 +147,7 @@ fn cs_clone_simple( &[sym::clone, sym::AssertParamIsCopy], ); } else { - match substr { + match substr.fields { StaticStruct(vdata, ..) => { process_variant(vdata); } @@ -169,18 +169,17 @@ fn cs_clone(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> Blo cx.expr_call_global(field.span, fn_path.clone(), args) }; - let self_ident = Ident::new(kw::SelfUpper, trait_span); let ctor_path; let all_fields; let vdata; - match substr { + match substr.fields { Struct(vdata_, af) => { - ctor_path = cx.path(trait_span, vec![self_ident]); + ctor_path = cx.path(trait_span, vec![substr.type_ident]); all_fields = af; vdata = vdata_; } EnumMatching(.., variant, af) => { - ctor_path = cx.path(trait_span, vec![self_ident, variant.ident]); + ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]); all_fields = af; vdata = &variant.data; } diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 2f3d2058773d8..d8355d733a7f3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -68,7 +68,7 @@ fn show_substructure( return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new()))); } - let (ident, vdata, fields) = match substr { + let (ident, vdata, fields) = match substr.fields { Struct(vdata, fields) => (type_ident, vdata, fields), EnumMatching(v, fields) => (v.ident, &v.data, fields), AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, type_ident), diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 28526bdef6b9d..268153c1cbb31 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -37,9 +37,9 @@ pub(crate) fn expand_deriving_default( attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, trait_span, substr| { - match substr { + match substr.fields { StaticStruct(variant_data) => { - default_struct_substructure(cx, trait_span, variant_data) + default_struct_substructure(cx, trait_span, variant_data, substr.type_ident) } StaticEnum(enum_def) => { default_enum_substructure(cx, trait_span, enum_def, item.span) @@ -67,15 +67,16 @@ fn default_struct_substructure( cx: &ExtCtxt<'_>, trait_span: Span, variant_data: &VariantData, + type_ident: Ident, ) -> BlockOrExpr { let expr = match variant_data { - VariantData::Unit(_) => cx.expr_ident(trait_span, Ident::new(kw::SelfUpper, trait_span)), + VariantData::Unit(_) => cx.expr_ident(trait_span, type_ident), VariantData::Tuple(fields, _) => { let exprs = fields .iter() .map(|field| default_call(cx, field.span.with_ctxt(trait_span.ctxt()))) .collect(); - cx.expr_call_ident(trait_span, Ident::new(kw::SelfUpper, trait_span), exprs) + cx.expr_call_ident(trait_span, type_ident, exprs) } VariantData::Struct { fields, .. } => { let default_fields = fields @@ -95,7 +96,7 @@ fn default_struct_substructure( cx.field_imm(span, field.ident.unwrap(), value) }) .collect(); - cx.expr_struct_ident(trait_span, Ident::new(kw::SelfUpper, trait_span), default_fields) + cx.expr_struct_ident(trait_span, type_ident, default_fields) } }; BlockOrExpr::new_expr(expr) diff --git a/compiler/rustc_builtin_macros/src/deriving/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs index da38045994c7f..27be8a8cb6dff 100644 --- a/compiler/rustc_builtin_macros/src/deriving/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -72,7 +72,7 @@ fn cs_total_eq_assert(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<' } }; - match substr { + match substr.fields { StaticStruct(vdata, ..) => { process_variant(vdata); } diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index df95ccd99f3e6..edd1cf75488fc 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -88,7 +88,7 @@ pub(crate) fn expand_deriving_from( }; let self_kw = Ident::new(kw::SelfUpper, span); - let expr: Box = match substructure { + let expr: Box = match substructure.fields { StaticStruct(variant) => match variant { // Self { field: value } VariantData::Struct { .. } => cx.expr_struct_ident( diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8b15920511aca..fbbadce3a8816 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -177,7 +177,7 @@ use std::ops::Not; use std::vec; -pub(crate) use Substructure::*; +pub(crate) use SubstructureFields::*; pub(crate) use rustc_ast as ast; use rustc_ast::token::{IdentKind, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; @@ -281,8 +281,16 @@ pub(crate) struct FieldInfo { pub maybe_scalar: bool, } +pub(crate) struct Substructure<'a> { + pub fields: SubstructureFields<'a>, + // FIXME: this is currently required to avoid issues with attribute macros after derives, + // such as https://github.com/rust-lang/rust/issues/163800. + // Ideally we would just use `Self` instead. + pub type_ident: Ident, +} + /// A summary of the possible sets of fields. -pub(crate) enum Substructure<'a> { +pub(crate) enum SubstructureFields<'a> { /// A non-static method where `Self` is a struct. Struct(&'a ast::VariantData, Vec), @@ -474,9 +482,15 @@ impl<'a> TraitDef<'a> { let fields = struct_def.fields().iter(); let methods = self.methods.iter().filter_map(|method_def| { let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, span, StaticStruct(struct_def)) + method_def.call_substructure_method( + cx, + span, + StaticStruct(struct_def), + *ident, + ) } else { - method_def.expand_struct_method_body(cx, span, struct_def, is_packed) + method_def + .expand_struct_method_body(cx, span, struct_def, is_packed, *ident) }; method_def.create_method(cx, span, body) @@ -494,9 +508,9 @@ impl<'a> TraitDef<'a> { let fields = enum_def.variants.iter().flat_map(|variant| variant.data.fields()); let methods = self.methods.iter().filter_map(|method_def| { let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, span, StaticEnum(enum_def)) + method_def.call_substructure_method(cx, span, StaticEnum(enum_def), *ident) } else { - method_def.expand_enum_method_body(cx, span, enum_def) + method_def.expand_enum_method_body(cx, span, enum_def, *ident) }; method_def.create_method(cx, span, body) @@ -778,9 +792,10 @@ impl<'a> MethodDef<'a> { &self, cx: &ExtCtxt<'_>, span: Span, - substructure: Substructure<'_>, + fields: SubstructureFields<'_>, + type_ident: Ident, ) -> BlockOrExpr { - (self.combine_substructure)(cx, span, substructure) + (self.combine_substructure)(cx, span, Substructure { fields, type_ident }) } fn is_static(&self) -> bool { @@ -906,12 +921,13 @@ impl<'a> MethodDef<'a> { span: Span, struct_def: &'b VariantData, is_packed: bool, + type_ident: Ident, ) -> BlockOrExpr { let selflike_args = self.get_selflike_args(cx, span); let selflike_fields = create_struct_field_access_fields(span, cx, &selflike_args, struct_def, is_packed); - self.call_substructure_method(cx, span, Struct(struct_def, selflike_fields)) + self.call_substructure_method(cx, span, Struct(struct_def, selflike_fields), type_ident) } /// ``` @@ -954,6 +970,7 @@ impl<'a> MethodDef<'a> { cx: &ExtCtxt<'_>, span: Span, enum_def: &'b EnumDef, + type_ident: Ident, ) -> BlockOrExpr { let variants = &enum_def.variants; @@ -989,17 +1006,32 @@ impl<'a> MethodDef<'a> { // If the type is fieldless and the trait uses the discriminant and // there are multiple variants, we need just an operation on // the discriminant(s). - return self.call_substructure_method(cx, span, EnumDiscr(None)); + return self.call_substructure_method( + cx, + span, + EnumDiscr(None), + type_ident, + ); } FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless => { - return self.call_substructure_method(cx, span, AllFieldlessEnum(enum_def)); + return self.call_substructure_method( + cx, + span, + AllFieldlessEnum(enum_def), + type_ident, + ); } FieldlessVariantsStrategy::Default => (), } } else if let [variant] = variants.as_slice() { // If there is a single variant, we don't need an operation on // the discriminant(s). Just use the most degenerate result. - return self.call_substructure_method(cx, span, EnumMatching(variant, Vec::new())); + return self.call_substructure_method( + cx, + span, + EnumMatching(variant, Vec::new()), + type_ident, + ); } } @@ -1039,8 +1071,9 @@ impl<'a> MethodDef<'a> { // Self arg, assuming all are instances of VariantK. // Build up code associated with such a case. let substructure = EnumMatching(variant, fields); - let arm_expr = - self.call_substructure_method(cx, span, substructure).into_expr(cx, span); + let arm_expr = self + .call_substructure_method(cx, span, substructure, type_ident) + .into_expr(cx, span); cx.arm(span, single_pat, arm_expr) }) @@ -1052,8 +1085,13 @@ impl<'a> MethodDef<'a> { Some(v) if unify_fieldless_variants => { // We need a default case that handles all the fieldless variants. Some( - self.call_substructure_method(cx, span, EnumMatching(v, Vec::new())) - .into_expr(cx, span), + self.call_substructure_method( + cx, + span, + EnumMatching(v, Vec::new()), + type_ident, + ) + .into_expr(cx, span), ) } _ if variants.len() > 1 && selflike_args.len() > 1 => { @@ -1090,7 +1128,12 @@ impl<'a> MethodDef<'a> { // is enough. if unify_fieldless_variants && variants.len() > 1 { // Combine a discriminant check with the match. - self.call_substructure_method(cx, span, EnumDiscr(Some(get_match_expr(selflike_args)))) + self.call_substructure_method( + cx, + span, + EnumDiscr(Some(get_match_expr(selflike_args))), + type_ident, + ) } else { BlockOrExpr(ThinVec::new(), Some(get_match_expr(selflike_args))) } diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 3e0722988155c..db0e8efc99f3c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -65,7 +65,7 @@ fn hash_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> cx.stmt_expr(expr) }; - let (stmts, match_expr) = match substr { + let (stmts, match_expr) = match substr.fields { Struct(_, fields) | EnumMatching(.., fields) => { let stmts = fields.into_iter().map(|field| call_hash(field.span, field.self_expr)).collect(); diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 377a32dcca4f0..180800aa72025 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -119,7 +119,7 @@ fn get_substructure_equality_expr( span: Span, substructure: Substructure<'_>, ) -> BlockOrExpr { - BlockOrExpr::new_expr(match substructure { + BlockOrExpr::new_expr(match substructure.fields { EnumMatching(.., fields) | Struct(.., fields) => { let combine = move |acc, field: &FieldInfo| { let rhs = field diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 8c3e2ee58f8e2..4ce695a16200f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -202,7 +202,7 @@ pub(crate) fn cmp_body( } }; - match substructure { + match substructure.fields { EnumMatching(.., all_fields) | Struct(_, all_fields) => { let op = |old, field: FieldInfo| { // The basic case: a field expression for one or more selflike args. E.g. diff --git a/tests/ui/derives/attr-macro-changes-type-kind.rs b/tests/ui/derives/attr-macro-changes-type-kind.rs new file mode 100644 index 0000000000000..98e05af3b33b6 --- /dev/null +++ b/tests/ui/derives/attr-macro-changes-type-kind.rs @@ -0,0 +1,15 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/163800, +//! where the generated code always referred to `Self`, which was invalid +//! when an attribute macro rewrites the type to an enum. + +//@ check-pass +//@ proc-macro: struct-to-enum.rs + +extern crate struct_to_enum; +use struct_to_enum::*; + +#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[struct_to_enum::phantom] +struct Spooky; + +fn main() {} diff --git a/tests/ui/derives/auxiliary/struct-to-enum.rs b/tests/ui/derives/auxiliary/struct-to-enum.rs new file mode 100644 index 0000000000000..458d8453d5076 --- /dev/null +++ b/tests/ui/derives/auxiliary/struct-to-enum.rs @@ -0,0 +1,18 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn phantom(_: TokenStream, _: TokenStream) -> TokenStream { + " +mod __value_Spooky { + pub use super::Spooky::Spooky; +} +pub enum Spooky { + __Phantom(std::marker::PhantomData), + Spooky, +} +pub use self::__value_Spooky::*; + " + .parse() + .unwrap() +} diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index 05412aca82360..163658d2106dd 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -46,7 +46,7 @@ impl ::core::fmt::Debug for Empty { #[automatically_derived] impl ::core::default::Default for Empty { #[inline] - fn default() -> Self { Self } + fn default() -> Self { Empty } } #[automatically_derived] impl ::core::hash::Hash for Empty { @@ -109,7 +109,7 @@ impl ::core::fmt::Debug for Point { impl ::core::default::Default for Point { #[inline] fn default() -> Self { - Self { + Point { x: ::core::default::Default::default(), y: ::core::default::Default::default(), } @@ -193,7 +193,7 @@ impl ::core::fmt::Debug for PackedPoint { impl ::core::default::Default for PackedPoint { #[inline] fn default() -> Self { - Self { + PackedPoint { x: ::core::default::Default::default(), y: ::core::default::Default::default(), } @@ -270,7 +270,9 @@ impl ::core::fmt::Debug for TupleSingleField { #[automatically_derived] impl ::core::default::Default for TupleSingleField { #[inline] - fn default() -> Self { Self(::core::default::Default::default()) } + fn default() -> Self { + TupleSingleField(::core::default::Default::default()) + } } #[automatically_derived] impl ::core::convert::From for TupleSingleField { @@ -343,7 +345,9 @@ impl ::core::fmt::Debug for SingleField { #[automatically_derived] impl ::core::default::Default for SingleField { #[inline] - fn default() -> Self { Self { foo: ::core::default::Default::default() } } + fn default() -> Self { + SingleField { foo: ::core::default::Default::default() } + } } #[automatically_derived] impl ::core::convert::From for SingleField { @@ -431,7 +435,7 @@ impl ::core::fmt::Debug for Big { impl ::core::default::Default for Big { #[inline] fn default() -> Self { - Self { + Big { b1: ::core::default::Default::default(), b2: ::core::default::Default::default(), b3: ::core::default::Default::default(), @@ -622,7 +626,7 @@ struct NonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for NonCopy { #[inline] - fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) } + fn clone(&self) -> Self { NonCopy(::core::clone::Clone::clone(&self.0)) } } // A packed struct that doesn't impl `Copy`, which means it gets the non-trivial @@ -632,7 +636,9 @@ struct PackedNonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedNonCopy { #[inline] - fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&{ self.0 })) } + fn clone(&self) -> Self { + PackedNonCopy(::core::clone::Clone::clone(&{ self.0 })) + } } // A struct that impls `Copy` manually, which means it gets the non-trivial @@ -641,7 +647,9 @@ struct ManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for ManualCopy { #[inline] - fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) } + fn clone(&self) -> Self { + ManualCopy(::core::clone::Clone::clone(&self.0)) + } } impl Copy for ManualCopy {} @@ -652,7 +660,9 @@ struct PackedManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedManualCopy { #[inline] - fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&{ self.0 })) } + fn clone(&self) -> Self { + PackedManualCopy(::core::clone::Clone::clone(&{ self.0 })) + } } impl Copy for PackedManualCopy {} @@ -725,7 +735,7 @@ impl ::core::clone::Clone for Generic where T::A: ::core::clone::Clone { #[inline] fn clone(&self) -> Self { - Self { + Generic { t: ::core::clone::Clone::clone(&self.t), ta: ::core::clone::Clone::clone(&self.ta), u: ::core::clone::Clone::clone(&self.u), @@ -751,7 +761,7 @@ impl T::A: ::core::default::Default { #[inline] fn default() -> Self { - Self { + Generic { t: ::core::default::Default::default(), ta: ::core::default::Default::default(), u: ::core::default::Default::default(), @@ -844,7 +854,7 @@ impl Self { - Self(::core::clone::Clone::clone(&{ self.0 }), + PackedGeneric(::core::clone::Clone::clone(&{ self.0 }), ::core::clone::Clone::clone(&{ self.1 }), ::core::clone::Clone::clone(&{ self.2 })) } @@ -871,7 +881,7 @@ impl T::A: ::core::default::Default { #[inline] fn default() -> Self { - Self(::core::default::Default::default(), + PackedGeneric(::core::default::Default::default(), ::core::default::Default::default(), ::core::default::Default::default()) } @@ -1019,7 +1029,7 @@ impl ::core::clone::Clone for Enum1 { fn clone(&self) -> Self { match self { Self::Single { x: __self_0 } => - Self::Single { x: ::core::clone::Clone::clone(__self_0) }, + Enum1::Single { x: ::core::clone::Clone::clone(__self_0) }, } } } @@ -1093,7 +1103,7 @@ enum Fieldless1 { #[automatically_derived] impl ::core::clone::Clone for Fieldless1 { #[inline] - fn clone(&self) -> Self { Self::A } + fn clone(&self) -> Self { Fieldless1::A } } #[automatically_derived] impl ::core::fmt::Debug for Fieldless1 { @@ -1408,11 +1418,11 @@ impl ::core::clone::Clone for Fielded { fn clone(&self) -> Self { match self { Self::X(__self_0) => - Self::X(::core::clone::Clone::clone(__self_0)), + Fielded::X(::core::clone::Clone::clone(__self_0)), Self::Y(__self_0) => - Self::Y(::core::clone::Clone::clone(__self_0)), + Fielded::Y(::core::clone::Clone::clone(__self_0)), Self::Z(__self_0) => - Self::Z(::core::clone::Clone::clone(__self_0)), + Fielded::Z(::core::clone::Clone::clone(__self_0)), } } } @@ -1511,9 +1521,9 @@ impl ::core::clone::Clone fn clone(&self) -> Self { match self { Self::One(__self_0) => - Self::One(::core::clone::Clone::clone(__self_0)), + EnumGeneric::One(::core::clone::Clone::clone(__self_0)), Self::Two(__self_0) => - Self::Two(::core::clone::Clone::clone(__self_0)), + EnumGeneric::Two(::core::clone::Clone::clone(__self_0)), } } } @@ -1712,7 +1722,9 @@ impl ::core::marker::Copy for FooCloneAndCopy { } #[automatically_derived] impl ::core::clone::Clone for FooCloneAndCopy { #[inline] - fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) } + fn clone(&self) -> Self { + FooCloneAndCopy(::core::clone::Clone::clone(&self.0)) + } } struct FooPartialOrdOrd(i32); diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index efc3785878c39..e549d315e7fdb 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -2,11 +2,11 @@ macro-stats ==================================================================== macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- -macro-stats #[derive(Clone)] 8 67 8.4 1_909 238.6 +macro-stats #[derive(Clone)] 8 67 8.4 1_895 236.9 macro-stats #[derive(Hash)] 2 17 8.5 536 268.0 macro-stats q! 1 26 26.0 519 519.0 macro-stats #[derive(Ord)] 1 15 15.0 505 505.0 -macro-stats #[derive(Default)] 2 16 8.0 409 204.5 +macro-stats #[derive(Default)] 2 16 8.0 407 203.5 macro-stats #[derive(Eq)] 1 11 11.0 312 312.0 macro-stats #[derive(Debug)] 1 8 8.0 277 277.0 macro-stats #[derive(PartialEq)] 1 9 9.0 269 269.0 From aec15eebbab119e3fcc06cdf252de74c742f5775 Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 6 Oct 2026 09:55:57 +0200 Subject: [PATCH 20/24] Remove CLAUDE.md Claude Code loads AGENTS.md since 2.1.277, released September 18. See https://code.claude.com/docs/en/changelog#2-1-277. --- CLAUDE.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 43c994c2d3617..0000000000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -@AGENTS.md From 9ce47def2fdd2e380cb52a9379acc31e55bf2264 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 6 Oct 2026 11:27:31 +0200 Subject: [PATCH 21/24] explicitly check for fresh vars in canonicalize --- .../rustc_next_trait_solver/src/canonical/canonicalizer.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 75c7513758cd0..ea19d36f5d0cf 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -13,12 +13,17 @@ use thin_vec::ThinVec; use crate::delegate::SolverDelegate; /// Does this have infer/placeholder/param, free regions or ReErased? +// We're explicitly checking for fresh types and consts to trigger an +// assert if they ever leak into the trait solver. They should never +// exist with the new solver. const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits( TypeFlags::HAS_INFER.bits() | TypeFlags::HAS_PLACEHOLDER.bits() | TypeFlags::HAS_PARAM.bits() | TypeFlags::HAS_FREE_REGIONS.bits() - | TypeFlags::HAS_RE_ERASED.bits(), + | TypeFlags::HAS_RE_ERASED.bits() + | TypeFlags::HAS_TY_FRESH.bits() + | TypeFlags::HAS_CT_FRESH.bits(), ) .unwrap(); From 2553cca6ed507337710e2bb4ac59ef79066eb9a6 Mon Sep 17 00:00:00 2001 From: b1yd <2156864690@qq.com> Date: Tue, 6 Oct 2026 16:31:21 +0800 Subject: [PATCH 22/24] add if-installed:auto:spellcheck to pre-push script --- src/etc/pre-push.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh index fb2007db9f12c..6304fabbbf6f5 100755 --- a/src/etc/pre-push.sh +++ b/src/etc/pre-push.sh @@ -35,7 +35,7 @@ echo "Running pre-push script $ROOT_DIR/x test tidy" cd "$ROOT_DIR" ./x test tidy \ --set build.locked-deps=true \ - --extra-checks auto:py,auto:cpp,auto:js + --extra-checks auto:py,auto:cpp,auto:js,if-installed:auto:spellcheck if [ $? -ne 0 ]; then echo "You may use \`git push --no-verify\` to skip this check." exit 1 From b71426dd949836796c29261c625c11cd383d741d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 6 Oct 2026 12:38:42 +0200 Subject: [PATCH 23/24] Add regression test for duplicated rustdoc search results between std and core --- tests/rustdoc-js-std/core-std-duplicates.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/rustdoc-js-std/core-std-duplicates.js diff --git a/tests/rustdoc-js-std/core-std-duplicates.js b/tests/rustdoc-js-std/core-std-duplicates.js new file mode 100644 index 0000000000000..4647ec6408746 --- /dev/null +++ b/tests/rustdoc-js-std/core-std-duplicates.js @@ -0,0 +1,21 @@ +// This test ensures that search results are not duplicated between `std` and `core`. +// Regression test for . + +// exact-check + +const EXPECTED = [ + { + 'query': 'primitive:char', + 'others': [ + { 'path': 'std', 'name': 'char' }, + ], + }, + { + 'query': 'char->u32', + 'others': [ + { 'path': 'std::u32', 'name': 'from' }, + { 'path': 'std::char', 'name': 'to_u32' }, + { 'path': 'std::char', 'name': 'to_digit' }, + ], + }, +]; From 7c69454685b76baf318e969ad6a13077292981ec Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Tue, 6 Oct 2026 13:40:59 +0200 Subject: [PATCH 24/24] Don't add rustc to env in nix dev shell --- src/tools/nix-dev-shell/x/default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/nix-dev-shell/x/default.nix b/src/tools/nix-dev-shell/x/default.nix index 915158080e421..db42d57249ede 100644 --- a/src/tools/nix-dev-shell/x/default.nix +++ b/src/tools/nix-dev-shell/x/default.nix @@ -29,13 +29,12 @@ stdenv.mkDerivation (self: { dontUnpack = true; nativeBuildInputs = [ - rustc makeBinaryWrapper ]; env.PYTHON = python3.interpreter; buildPhase = '' - rustc -Copt-level=3 --crate-name x $src --out-dir $unwrapped/bin + ${rustc}/bin/rustc -Copt-level=3 --crate-name x $src --out-dir $unwrapped/bin ''; installPhase =