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 1/4] 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 fa3bfde261f62d8a8acb3dd0da2133ca0e92164d Mon Sep 17 00:00:00 2001 From: xonx4l Date: Thu, 1 Oct 2026 16:44:49 +0530 Subject: [PATCH 2/4] 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 341977a991b60e14a10172d9d7e0b73e17f4541d Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Mon, 5 Oct 2026 15:09:28 +0200 Subject: [PATCH 3/4] Adjust the adjustment to wasi TLS to no longer adjust --- library/std/src/sys/thread_local/mod.rs | 8 ++++---- src/doc/rustc/src/platform-support/wasm32-wasip1.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 809ef5cfe9c60..f86d25e38efb5 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -35,7 +35,7 @@ cfg_select! { any( - all(target_family = "wasm", not(target_feature = "atomics"), not(target_env = "p3")), + all(target_family = "wasm", not(target_feature = "atomics"), not(target_os = "wasi")), target_os = "uefi", target_os = "zkvm", target_os = "trusty", @@ -66,7 +66,7 @@ cfg_select! { /// single callback that runs all of the destructors in the list. #[cfg(all( target_thread_local, - not(all(target_family = "wasm", not(target_feature = "atomics"), not(target_env = "p3"))) + not(all(target_family = "wasm", not(target_feature = "atomics"), not(target_os = "wasi"))) ))] pub(crate) mod destructors { cfg_select! { @@ -106,7 +106,7 @@ pub(crate) mod guard { pub(crate) use windows::enable; } any( - all(target_family = "wasm", not(target_env = "p3")), + all(target_family = "wasm", not(target_os = "wasi")), target_os = "uefi", target_os = "zkvm", target_os = "trusty", @@ -154,7 +154,7 @@ pub(crate) mod key { all(not(target_vendor = "apple"), not(target_family = "wasm"), target_family = "unix"), all(not(target_thread_local), target_vendor = "apple"), target_os = "teeos", - all(target_os = "wasi", target_env = "p3"), + target_os = "wasi", ) => { mod racy; mod unix; diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index 16499659291a0..3cc0f5a96c597 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -73,13 +73,13 @@ be used instead. ## Building the target in rustc To build this target first acquire a copy of [`wasi-sdk`]. At this time version -33 is the minimum needed. +34 is the minimum needed. Next configure the `WASI_SDK_PATH` environment variable to point to where this is installed. For example: ```text -export WASI_SDK_PATH=/path/to/wasi-sdk-33.0 +export WASI_SDK_PATH=/path/to/wasi-sdk-34.0 ``` Next be sure to enable LLD when building Rust from source as LLVM's `wasm-ld` From 54a6d2e4c750c76885dc444ec5eb97a30e85a695 Mon Sep 17 00:00:00 2001 From: xonx4l Date: Mon, 5 Oct 2026 23:29:44 +0530 Subject: [PATCH 4/4] 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) + }); } }