From 6d2c6f9c5a526a956416d9f61aabe4c0d31472c2 Mon Sep 17 00:00:00 2001 From: DaAlbrecht Date: Wed, 8 Oct 2025 23:23:23 +0200 Subject: [PATCH 1/7] feat: setup new lint --- .../style/bevy_platform_alternative_exists.rs | 67 +++++++++++++++++++ bevy_lint/src/lints/style/mod.rs | 9 ++- .../bevy_platform_alternative_exists/main.rs | 7 ++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs create mode 100644 bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs diff --git a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs new file mode 100644 index 00000000..2846a256 --- /dev/null +++ b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs @@ -0,0 +1,67 @@ +use clippy_utils::ty::ty_from_hir_ty; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; + +use crate::{declare_bevy_lint, declare_bevy_lint_pass}; + +declare_bevy_lint! { + pub(crate) BEVY_PLATFORM_ALTERNATIVE_EXISTS, + super::Style, + "Used type from the `std` that has an existing alternative from `bevy_platform`", +} + +declare_bevy_lint_pass! { + pub(crate) BevyPlatformAlternativeExists => [BEVY_PLATFORM_ALTERNATIVE_EXISTS], +} + +impl<'tcx> LateLintPass<'tcx> for BevyPlatformAlternativeExists { + fn check_ty( + &mut self, + cx: &LateContext<'tcx>, + hir_ty: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>, + ) { + if hir_ty.span.in_external_macro(cx.tcx.sess.source_map()) { + return; + } + let ty = ty_from_hir_ty(cx, hir_ty.as_unambig_ty()); + + if let Some(platform_type) = BevyPlatformTypes::try_from_ty(cx, ty) { + // TODO: lint + } + dbg!(ty); + } +} + +enum BevyPlatformTypes { + Instant, + RwLock, + RwLockReadGuard, + RwLockWriteGuard, + LockResult, + TryLockError, + TryLockResult, + Once, + OnceState, + OnceLock, + Mutex, + MutexGuard, + LazyLock, + Barrier, + BarrierWaitResult, + // TODO: atomics + HashTable, + HashSet, + HashMap, + // cell + SyncUnsafeCell, + Exclusive, +} + +impl BevyPlatformTypes { + fn try_from_ty(cx: &LateContext, ty: Ty) -> Option { + if crate::paths::bevy_platform_types::STD_INSTANT.matches_ty(cx, ty) { + dbg!("found"); + } + None + } +} diff --git a/bevy_lint/src/lints/style/mod.rs b/bevy_lint/src/lints/style/mod.rs index f7a9fc6b..904522ce 100644 --- a/bevy_lint/src/lints/style/mod.rs +++ b/bevy_lint/src/lints/style/mod.rs @@ -8,6 +8,7 @@ use rustc_lint::{Level, Lint, LintStore}; use crate::lint::LintGroup; +pub mod bevy_platform_alternative_exists; pub mod unconventional_naming; pub(crate) struct Style; @@ -15,9 +16,15 @@ pub(crate) struct Style; impl LintGroup for Style { const NAME: &str = "bevy::style"; const LEVEL: Level = Level::Warn; - const LINTS: &[&Lint] = &[unconventional_naming::UNCONVENTIONAL_NAMING]; + const LINTS: &[&Lint] = &[ + bevy_platform_alternative_exists::BEVY_PLATFORM_ALTERNATIVE_EXISTS, + unconventional_naming::UNCONVENTIONAL_NAMING, + ]; fn register_passes(store: &mut LintStore) { + store.register_late_pass(|_| { + Box::new(bevy_platform_alternative_exists::BevyPlatformAlternativeExists) + }); store.register_late_pass(|_| Box::new(unconventional_naming::UnconventionalNaming)); } } diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs new file mode 100644 index 00000000..21f8c9dc --- /dev/null +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs @@ -0,0 +1,7 @@ +#![feature(register_tool)] +#![register_tool(bevy)] +#![deny(bevy::bevy_platform_alternative_exists)] + +fn main() { + let foo: std::time::Instant = std::time::Instant::now(); +} From 196eff186b69165bb29932519246fe3d2b865843 Mon Sep 17 00:00:00 2001 From: DaAlbrecht Date: Thu, 9 Oct 2025 23:22:20 +0200 Subject: [PATCH 2/7] feat: add all symbols and paths --- .../style/bevy_platform_alternative_exists.rs | 144 ++++++++++++++---- bevy_lint/src/paths.rs | 29 ++++ bevy_lint/src/sym.rs | 27 +++- .../bevy_platform_alternative_exists/main.rs | 2 +- 4 files changed, 170 insertions(+), 32 deletions(-) diff --git a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs index 2846a256..17ab2fbb 100644 --- a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs +++ b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs @@ -1,4 +1,4 @@ -use clippy_utils::ty::ty_from_hir_ty; +use clippy_utils::{diagnostics::span_lint_hir_and_then, source::snippet_opt, ty::ty_from_hir_ty}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; @@ -23,45 +23,137 @@ impl<'tcx> LateLintPass<'tcx> for BevyPlatformAlternativeExists { if hir_ty.span.in_external_macro(cx.tcx.sess.source_map()) { return; } + + // lower the [`hir::Ty`] to a [`rustc_middle::ty::Ty`] let ty = ty_from_hir_ty(cx, hir_ty.as_unambig_ty()); - if let Some(platform_type) = BevyPlatformTypes::try_from_ty(cx, ty) { - // TODO: lint + // Check if for the given `ty` an alternative from `bevy_platform` exists. + if let Some(bevy_platform_alternative) = BevyPlatformTypes::try_from_ty(cx, ty) { + span_lint_hir_and_then( + cx, + BEVY_PLATFORM_ALTERNATIVE_EXISTS, + hir_ty.hir_id, + hir_ty.span, + BEVY_PLATFORM_ALTERNATIVE_EXISTS.desc, + |diag| { + diag.note(format!( + "the type `{}` can be replaced with the no_std compatible type \"bevy_platform::{}\"", + snippet_opt(cx.tcx.sess, hir_ty.span), + conventional_name_impl.suffix() + )); + + diag.span_suggestion( + struct_span, + format!("use `{}` instead", struct_name.as_str()), + conventional_name_impl.name_suggestion(struct_name.as_str()), + Applicability::MaybeIncorrect, + ); + }, + ); } - dbg!(ty); } } +/// Represents all the types in the `bevy_platform` crate that +/// are drop in replacements for the equivalently named std types. enum BevyPlatformTypes { - Instant, - RwLock, - RwLockReadGuard, - RwLockWriteGuard, + // cell: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/cell/mod.rs + SyncCell, + SyncUnsafeCell, + // collections: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/collections/mod.rs + HashMap, + HashSet, + // sync: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/sync/mod.rs + Barrier, + BarrierWaitResult, + LazyLock, + Mutex, + MutexGuard, + Once, + OnceLock, + OnceState, LockResult, + PoisonError, TryLockError, TryLockResult, - Once, - OnceState, - OnceLock, - Mutex, - MutexGuard, - LazyLock, - Barrier, - BarrierWaitResult, - // TODO: atomics - HashTable, - HashSet, - HashMap, - // cell - SyncUnsafeCell, - Exclusive, + RwLock, + RwLockReadGuard, + RwLockWriteGuard, + // time: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/time/mod.rs + Instant, } impl BevyPlatformTypes { fn try_from_ty(cx: &LateContext, ty: Ty) -> Option { - if crate::paths::bevy_platform_types::STD_INSTANT.matches_ty(cx, ty) { - dbg!("found"); + use crate::paths::bevy_platform_types::*; + + if SYNCCELL.matches_ty(cx, ty) { + Some(BevyPlatformTypes::SyncCell) + } else if SYNCUNSAFECELL.matches_ty(cx, ty) { + Some(BevyPlatformTypes::SyncUnsafeCell) + } else if HASHMAP.matches_ty(cx, ty) { + Some(BevyPlatformTypes::HashMap) + } else if HASHSET.matches_ty(cx, ty) { + Some(BevyPlatformTypes::HashSet) + } else if INSTANT.matches_ty(cx, ty) { + Some(BevyPlatformTypes::Instant) + } else if BARRIER.matches_ty(cx, ty) { + Some(BevyPlatformTypes::Barrier) + } else if BARRIERWAITRESULT.matches_ty(cx, ty) { + Some(BevyPlatformTypes::BarrierWaitResult) + } else if LAZYLOCK.matches_ty(cx, ty) { + Some(BevyPlatformTypes::LazyLock) + } else if MUTEX.matches_ty(cx, ty) { + Some(BevyPlatformTypes::Mutex) + } else if MUTEXGUARD.matches_ty(cx, ty) { + Some(BevyPlatformTypes::MutexGuard) + } else if ONCE.matches_ty(cx, ty) { + Some(BevyPlatformTypes::Once) + } else if ONCELOCK.matches_ty(cx, ty) { + Some(BevyPlatformTypes::OnceLock) + } else if ONCESTATE.matches_ty(cx, ty) { + Some(BevyPlatformTypes::OnceState) + } else if LOCKRESULT.matches_ty(cx, ty) { + Some(BevyPlatformTypes::LockResult) + } else if POISONERROR.matches_ty(cx, ty) { + Some(BevyPlatformTypes::PoisonError) + } else if TRYLOCKERROR.matches_ty(cx, ty) { + Some(BevyPlatformTypes::TryLockError) + } else if TRYLOCKRESULT.matches_ty(cx, ty) { + Some(BevyPlatformTypes::TryLockResult) + } else if RWLOCK.matches_ty(cx, ty) { + Some(BevyPlatformTypes::RwLock) + } else if RWLOCKREADGUARD.matches_ty(cx, ty) { + Some(BevyPlatformTypes::RwLockReadGuard) + } else if RWLOCKWRITEGUARD.matches_ty(cx, ty) { + Some(BevyPlatformTypes::RwLockWriteGuard) + } else { + None + } + } + + fn name(&self) -> &'static str { + match self { + BevyPlatformTypes::SyncCell => "SyncCell", + BevyPlatformTypes::SyncUnsafeCell => "SyncUnsafeCell", + BevyPlatformTypes::HashMap => "HashMap", + BevyPlatformTypes::HashSet => "HashSet", + BevyPlatformTypes::Barrier => "Barrier", + BevyPlatformTypes::BarrierWaitResult => "BarrierWaitResult", + BevyPlatformTypes::LazyLock => "LazyLock", + BevyPlatformTypes::Mutex => "Mutex", + BevyPlatformTypes::MutexGuard => "MutexGuard", + BevyPlatformTypes::Once => "Once", + BevyPlatformTypes::OnceLock => "OnceLock", + BevyPlatformTypes::OnceState => "OnceState", + BevyPlatformTypes::LockResult => "LockResult", + BevyPlatformTypes::PoisonError => "PoisonError", + BevyPlatformTypes::TryLockError => "TryLockError", + BevyPlatformTypes::TryLockResult => "TryLockResult", + BevyPlatformTypes::RwLock => "RwLock", + BevyPlatformTypes::RwLockReadGuard => "RwLockReadGuard", + BevyPlatformTypes::RwLockWriteGuard => "RwLockWriteGuard", + BevyPlatformTypes::Instant => "Instant", } - None } } diff --git a/bevy_lint/src/paths.rs b/bevy_lint/src/paths.rs index 9ed21c38..2c227867 100644 --- a/bevy_lint/src/paths.rs +++ b/bevy_lint/src/paths.rs @@ -86,3 +86,32 @@ pub static UPDATE: PathLookup = type_path!(bevy_app::main_schedule::Update); pub static WITH: PathLookup = type_path!(bevy_ecs::query::filter::With); /// pub static WORLD: PathLookup = type_path!(bevy_ecs::world::World); + +// All the paths that represent the `bevy_platform` types. +// Keep the following list alphabetically sorted :) +pub mod bevy_platform_types { + use clippy_utils::paths::{PathLookup, PathNS}; + + use crate::sym; + + pub static SYNCCELL: PathLookup = type_path!(std::sync::Exclusive); + pub static SYNCUNSAFECELL: PathLookup = type_path!(std::cell::SyncUnsafeCell); + pub static INSTANT: PathLookup = type_path!(std::time::Instant); + pub static HASHMAP: PathLookup = type_path!(std::collections::HashMap); + pub static HASHSET: PathLookup = type_path!(std::collections::HashSet); + pub static BARRIER: PathLookup = type_path!(std::sync::Barrier); + pub static BARRIERWAITRESULT: PathLookup = type_path!(std::sync::BarrierWaitResult); + pub static LAZYLOCK: PathLookup = type_path!(std::sync::LazyLock); + pub static MUTEX: PathLookup = type_path!(std::sync::Mutex); + pub static MUTEXGUARD: PathLookup = type_path!(std::sync::MutexGuard); + pub static ONCE: PathLookup = type_path!(std::sync::Once); + pub static ONCELOCK: PathLookup = type_path!(std::sync::OnceLock); + pub static ONCESTATE: PathLookup = type_path!(std::sync::OnceState); + pub static LOCKRESULT: PathLookup = type_path!(std::sync::LockResult); + pub static POISONERROR: PathLookup = type_path!(std::sync::PoisonError); + pub static TRYLOCKERROR: PathLookup = type_path!(std::sync::TryLockError); + pub static TRYLOCKRESULT: PathLookup = type_path!(std::sync::TryLockResult); + pub static RWLOCK: PathLookup = type_path!(std::sync::RwLock); + pub static RWLOCKREADGUARD: PathLookup = type_path!(std::sync::RwLockReadGuard); + pub static RWLOCKWRITEGUARD: PathLookup = type_path!(std::sync::RwLockWriteGuard); +} diff --git a/bevy_lint/src/sym.rs b/bevy_lint/src/sym.rs index bd88efb5..79552e1e 100644 --- a/bevy_lint/src/sym.rs +++ b/bevy_lint/src/sym.rs @@ -57,7 +57,10 @@ use clippy_utils::sym::EXTRA_SYMBOLS as CLIPPY_SYMBOLS; /// These are symbols that we use but are already interned by either the compiler or Clippy. pub use clippy_utils::sym::filter; -pub use rustc_span::sym::{bevy_ecs, bundle, message, plugin, reflect}; +pub use rustc_span::sym::{ + HashMap, HashSet, Instant, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard, + SyncUnsafeCell, bevy_ecs, bundle, message, plugin, reflect, std, sync, +}; use rustc_span::{Symbol, symbol::PREDEFINED_SYMBOLS_COUNT}; /// The starting offset used for the first Bevy-specific symbol. @@ -114,26 +117,30 @@ macro_rules! declare_bevy_symbols { // Before adding a new symbol here, check that it doesn't exist yet in `rustc_span::sym` or // `clippy_utils::sym`. Having duplicate symbols will cause the compiler to ICE! Also please keep -// this list alphabetically sorted :) +// this list alphabetically sorted :) (use `:sort i` in nvim) declare_bevy_symbols! { add_systems, app, App, + Barrier, + BarrierWaitResult, + bevy, bevy_app, bevy_camera, bevy_ptr, bevy_reflect, - bevy, Bundle, camera, Camera, + cell, change_detection, + collections, commands, Commands, component, Component, - deferred_world, Deferred, + deferred_world, DeferredWorld, entity_ref, EntityCommands, @@ -141,11 +148,13 @@ declare_bevy_symbols! { event, Event, Events, + Exclusive, FilteredEntityMut, FixedUpdate, init_resource, insert_resource, iter_current_update_messages, + LazyLock, main_schedule, Message, Messages, @@ -169,13 +178,21 @@ declare_bevy_symbols! { schedule, set, spawn, - system_param, system, + system_param, SystemSet, + time, Update, With, world, World, + Once, + OnceLock, + OnceState, + LockResult, + PoisonError, + TryLockError, + TryLockResult, } /// Returns a list of strings that should be supplied to diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs index 21f8c9dc..648d10c5 100644 --- a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs @@ -3,5 +3,5 @@ #![deny(bevy::bevy_platform_alternative_exists)] fn main() { - let foo: std::time::Instant = std::time::Instant::now(); + let _ = std::time::Instant::now(); } From 557d8c87525225d92ba349668228b97aa57fda57 Mon Sep 17 00:00:00 2001 From: DaAlbrecht Date: Sun, 12 Oct 2025 12:40:46 +0200 Subject: [PATCH 3/7] feat: switch to marco, only lint and help --- .../style/bevy_platform_alternative_exists.rs | 180 ++++++------------ 1 file changed, 63 insertions(+), 117 deletions(-) diff --git a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs index 17ab2fbb..19eae5c2 100644 --- a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs +++ b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs @@ -1,6 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_hir_and_then, source::snippet_opt, ty::ty_from_hir_ty}; +use clippy_utils::{diagnostics::span_lint_and_help, source::snippet, ty::ty_from_hir_ty}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; use crate::{declare_bevy_lint, declare_bevy_lint_pass}; @@ -28,132 +27,79 @@ impl<'tcx> LateLintPass<'tcx> for BevyPlatformAlternativeExists { let ty = ty_from_hir_ty(cx, hir_ty.as_unambig_ty()); // Check if for the given `ty` an alternative from `bevy_platform` exists. - if let Some(bevy_platform_alternative) = BevyPlatformTypes::try_from_ty(cx, ty) { - span_lint_hir_and_then( + if let Some(bevy_platform_alternative) = BevyPlatformType::try_from_ty(cx, ty) { + span_lint_and_help( cx, BEVY_PLATFORM_ALTERNATIVE_EXISTS, - hir_ty.hir_id, hir_ty.span, BEVY_PLATFORM_ALTERNATIVE_EXISTS.desc, - |diag| { - diag.note(format!( - "the type `{}` can be replaced with the no_std compatible type \"bevy_platform::{}\"", - snippet_opt(cx.tcx.sess, hir_ty.span), - conventional_name_impl.suffix() - )); - - diag.span_suggestion( - struct_span, - format!("use `{}` instead", struct_name.as_str()), - conventional_name_impl.name_suggestion(struct_name.as_str()), - Applicability::MaybeIncorrect, - ); - }, + None, + format!( + "the type `{}` can be replaced with the `no_std` compatible type + from `bevy_platform` {}", + snippet(cx.tcx.sess, hir_ty.span, ""), + bevy_platform_alternative.name(), + ), ); } } } -/// Represents all the types in the `bevy_platform` crate that -/// are drop in replacements for the equivalently named std types. -enum BevyPlatformTypes { - // cell: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/cell/mod.rs - SyncCell, - SyncUnsafeCell, - // collections: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/collections/mod.rs - HashMap, - HashSet, - // sync: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/sync/mod.rs - Barrier, - BarrierWaitResult, - LazyLock, - Mutex, - MutexGuard, - Once, - OnceLock, - OnceState, - LockResult, - PoisonError, - TryLockError, - TryLockResult, - RwLock, - RwLockReadGuard, - RwLockWriteGuard, - // time: https://github.com/bevyengine/bevy/blob/v0.17.2/crates/bevy_platform/src/time/mod.rs - Instant, -} +macro_rules! declare_bevy_platform_types { + ( + $( + $variant:ident => $path:ident + ) + ,+$(,)? + ) => { + #[derive(Copy, Clone)] + pub enum BevyPlatformType { + $( + $variant, + )+ + } -impl BevyPlatformTypes { - fn try_from_ty(cx: &LateContext, ty: Ty) -> Option { - use crate::paths::bevy_platform_types::*; + impl BevyPlatformType{ + pub const fn name(&self) -> &'static str { + match self { + $(Self::$variant => stringify!($variant),)+ + } + } - if SYNCCELL.matches_ty(cx, ty) { - Some(BevyPlatformTypes::SyncCell) - } else if SYNCUNSAFECELL.matches_ty(cx, ty) { - Some(BevyPlatformTypes::SyncUnsafeCell) - } else if HASHMAP.matches_ty(cx, ty) { - Some(BevyPlatformTypes::HashMap) - } else if HASHSET.matches_ty(cx, ty) { - Some(BevyPlatformTypes::HashSet) - } else if INSTANT.matches_ty(cx, ty) { - Some(BevyPlatformTypes::Instant) - } else if BARRIER.matches_ty(cx, ty) { - Some(BevyPlatformTypes::Barrier) - } else if BARRIERWAITRESULT.matches_ty(cx, ty) { - Some(BevyPlatformTypes::BarrierWaitResult) - } else if LAZYLOCK.matches_ty(cx, ty) { - Some(BevyPlatformTypes::LazyLock) - } else if MUTEX.matches_ty(cx, ty) { - Some(BevyPlatformTypes::Mutex) - } else if MUTEXGUARD.matches_ty(cx, ty) { - Some(BevyPlatformTypes::MutexGuard) - } else if ONCE.matches_ty(cx, ty) { - Some(BevyPlatformTypes::Once) - } else if ONCELOCK.matches_ty(cx, ty) { - Some(BevyPlatformTypes::OnceLock) - } else if ONCESTATE.matches_ty(cx, ty) { - Some(BevyPlatformTypes::OnceState) - } else if LOCKRESULT.matches_ty(cx, ty) { - Some(BevyPlatformTypes::LockResult) - } else if POISONERROR.matches_ty(cx, ty) { - Some(BevyPlatformTypes::PoisonError) - } else if TRYLOCKERROR.matches_ty(cx, ty) { - Some(BevyPlatformTypes::TryLockError) - } else if TRYLOCKRESULT.matches_ty(cx, ty) { - Some(BevyPlatformTypes::TryLockResult) - } else if RWLOCK.matches_ty(cx, ty) { - Some(BevyPlatformTypes::RwLock) - } else if RWLOCKREADGUARD.matches_ty(cx, ty) { - Some(BevyPlatformTypes::RwLockReadGuard) - } else if RWLOCKWRITEGUARD.matches_ty(cx, ty) { - Some(BevyPlatformTypes::RwLockWriteGuard) - } else { - None + pub fn try_from_ty(cx: &LateContext<'_>, ty: rustc_middle::ty::Ty<'_>) -> Option { + use crate::paths::bevy_platform_types::*; + $( + if $path.matches_ty(cx, ty) { + Some(Self::$variant) + } else + )+ + { + None + } + } } - } + }; +} - fn name(&self) -> &'static str { - match self { - BevyPlatformTypes::SyncCell => "SyncCell", - BevyPlatformTypes::SyncUnsafeCell => "SyncUnsafeCell", - BevyPlatformTypes::HashMap => "HashMap", - BevyPlatformTypes::HashSet => "HashSet", - BevyPlatformTypes::Barrier => "Barrier", - BevyPlatformTypes::BarrierWaitResult => "BarrierWaitResult", - BevyPlatformTypes::LazyLock => "LazyLock", - BevyPlatformTypes::Mutex => "Mutex", - BevyPlatformTypes::MutexGuard => "MutexGuard", - BevyPlatformTypes::Once => "Once", - BevyPlatformTypes::OnceLock => "OnceLock", - BevyPlatformTypes::OnceState => "OnceState", - BevyPlatformTypes::LockResult => "LockResult", - BevyPlatformTypes::PoisonError => "PoisonError", - BevyPlatformTypes::TryLockError => "TryLockError", - BevyPlatformTypes::TryLockResult => "TryLockResult", - BevyPlatformTypes::RwLock => "RwLock", - BevyPlatformTypes::RwLockReadGuard => "RwLockReadGuard", - BevyPlatformTypes::RwLockWriteGuard => "RwLockWriteGuard", - BevyPlatformTypes::Instant => "Instant", - } - } +declare_bevy_platform_types! { + Barrier => BARRIER, + BarrierWaitResult => BARRIERWAITRESULT, + HashMap => HASHMAP, + HashSet => HASHSET, + Instant => INSTANT, + LazyLock => LAZYLOCK, + LockResult => LOCKRESULT, + Mutex => MUTEX, + MutexGuard => MUTEXGUARD, + Once => ONCE, + OnceLock => ONCELOCK, + OnceState => ONCESTATE, + PoisonError => POISONERROR, + RwLock => RWLOCK, + RwLockReadGuard => RWLOCKREADGUARD, + RwLockWriteGuard => RWLOCKWRITEGUARD, + SyncCell => SYNCCELL, + SyncUnsafeCell => SYNCUNSAFECELL, + TryLockError => TRYLOCKERROR, + TryLockResult => TRYLOCKRESULT, } From a9f26d43c10aac455499edff663d7b41e4cf23b0 Mon Sep 17 00:00:00 2001 From: DaAlbrecht Date: Sun, 12 Oct 2025 13:04:55 +0200 Subject: [PATCH 4/7] feat: sort paths of `bevy_platform_types` --- bevy_lint/src/paths.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bevy_lint/src/paths.rs b/bevy_lint/src/paths.rs index 2c227867..b816f42c 100644 --- a/bevy_lint/src/paths.rs +++ b/bevy_lint/src/paths.rs @@ -88,30 +88,30 @@ pub static WITH: PathLookup = type_path!(bevy_ecs::query::filter::With); pub static WORLD: PathLookup = type_path!(bevy_ecs::world::World); // All the paths that represent the `bevy_platform` types. -// Keep the following list alphabetically sorted :) +// Keep the following list alphabetically sorted :) in neovim, use `:sort/\vpub static \w+/ ri` pub mod bevy_platform_types { use clippy_utils::paths::{PathLookup, PathNS}; use crate::sym; - pub static SYNCCELL: PathLookup = type_path!(std::sync::Exclusive); - pub static SYNCUNSAFECELL: PathLookup = type_path!(std::cell::SyncUnsafeCell); - pub static INSTANT: PathLookup = type_path!(std::time::Instant); - pub static HASHMAP: PathLookup = type_path!(std::collections::HashMap); - pub static HASHSET: PathLookup = type_path!(std::collections::HashSet); pub static BARRIER: PathLookup = type_path!(std::sync::Barrier); pub static BARRIERWAITRESULT: PathLookup = type_path!(std::sync::BarrierWaitResult); + pub static HASHMAP: PathLookup = type_path!(std::collections::HashMap); + pub static HASHSET: PathLookup = type_path!(std::collections::HashSet); + pub static INSTANT: PathLookup = type_path!(std::time::Instant); pub static LAZYLOCK: PathLookup = type_path!(std::sync::LazyLock); + pub static LOCKRESULT: PathLookup = type_path!(std::sync::LockResult); pub static MUTEX: PathLookup = type_path!(std::sync::Mutex); pub static MUTEXGUARD: PathLookup = type_path!(std::sync::MutexGuard); pub static ONCE: PathLookup = type_path!(std::sync::Once); pub static ONCELOCK: PathLookup = type_path!(std::sync::OnceLock); pub static ONCESTATE: PathLookup = type_path!(std::sync::OnceState); - pub static LOCKRESULT: PathLookup = type_path!(std::sync::LockResult); pub static POISONERROR: PathLookup = type_path!(std::sync::PoisonError); - pub static TRYLOCKERROR: PathLookup = type_path!(std::sync::TryLockError); - pub static TRYLOCKRESULT: PathLookup = type_path!(std::sync::TryLockResult); pub static RWLOCK: PathLookup = type_path!(std::sync::RwLock); pub static RWLOCKREADGUARD: PathLookup = type_path!(std::sync::RwLockReadGuard); pub static RWLOCKWRITEGUARD: PathLookup = type_path!(std::sync::RwLockWriteGuard); + pub static SYNCCELL: PathLookup = type_path!(std::sync::Exclusive); + pub static SYNCUNSAFECELL: PathLookup = type_path!(std::cell::SyncUnsafeCell); + pub static TRYLOCKERROR: PathLookup = type_path!(std::sync::TryLockError); + pub static TRYLOCKRESULT: PathLookup = type_path!(std::sync::TryLockResult); } From d183ebe6d024ff98b9a22f6a5a19a32eb2980038 Mon Sep 17 00:00:00 2001 From: DaAlbrecht Date: Sun, 12 Oct 2025 15:43:55 +0200 Subject: [PATCH 5/7] feat: extend macro to include full path to the declared type --- .../style/bevy_platform_alternative_exists.rs | 73 +++++++++++-------- .../bevy_platform_alternative_exists/main.rs | 3 + .../main.stderr | 15 ++++ 3 files changed, 61 insertions(+), 30 deletions(-) create mode 100644 bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr diff --git a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs index 19eae5c2..ff1558a3 100644 --- a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs +++ b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs @@ -35,20 +35,31 @@ impl<'tcx> LateLintPass<'tcx> for BevyPlatformAlternativeExists { BEVY_PLATFORM_ALTERNATIVE_EXISTS.desc, None, format!( - "the type `{}` can be replaced with the `no_std` compatible type - from `bevy_platform` {}", + "the type `{}` can be replaced with the `no_std` compatible type {}", snippet(cx.tcx.sess, hir_ty.span, ""), - bevy_platform_alternative.name(), + bevy_platform_alternative.full_path() ), ); } } } +/// Creates an enum containing all the types form `bevy_platform` as variants. +/// +/// # Example +/// +/// ```ignore +/// declare_bevy_platform_types! { +/// // The variant name => [`PathLookup`] that matches the equivalent type in the std. +/// CustomType => CUSTOMTYPE, +/// // Optional the module path can be passed too, default is `bevy_platform::`. +/// // If an additional module path is added, it will result in: `bevy_platform::custom::thread::CustomType`. +/// CustomType("custom::thread") => BARRIER, +/// ``` macro_rules! declare_bevy_platform_types { ( $( - $variant:ident => $path:ident + $variant:ident $(($mod_path:expr))? => $path:ident ) ,+$(,)? ) => { @@ -60,12 +71,7 @@ macro_rules! declare_bevy_platform_types { } impl BevyPlatformType{ - pub const fn name(&self) -> &'static str { - match self { - $(Self::$variant => stringify!($variant),)+ - } - } - + /// Try to create a [`BevyPlatformType`] from the given [`Ty`]. pub fn try_from_ty(cx: &LateContext<'_>, ty: rustc_middle::ty::Ty<'_>) -> Option { use crate::paths::bevy_platform_types::*; $( @@ -77,29 +83,36 @@ macro_rules! declare_bevy_platform_types { None } } + + ///Returns a string identifying this [`BevyPlatformType`]. This string is suitable for user output. + pub const fn full_path(&self) -> &'static str { + match self { + $(Self::$variant => concat!("bevy_platform", $("::", $mod_path,)? "::" , stringify!($variant)),)+ + } + } } }; } declare_bevy_platform_types! { - Barrier => BARRIER, - BarrierWaitResult => BARRIERWAITRESULT, - HashMap => HASHMAP, - HashSet => HASHSET, - Instant => INSTANT, - LazyLock => LAZYLOCK, - LockResult => LOCKRESULT, - Mutex => MUTEX, - MutexGuard => MUTEXGUARD, - Once => ONCE, - OnceLock => ONCELOCK, - OnceState => ONCESTATE, - PoisonError => POISONERROR, - RwLock => RWLOCK, - RwLockReadGuard => RWLOCKREADGUARD, - RwLockWriteGuard => RWLOCKWRITEGUARD, - SyncCell => SYNCCELL, - SyncUnsafeCell => SYNCUNSAFECELL, - TryLockError => TRYLOCKERROR, - TryLockResult => TRYLOCKRESULT, + Barrier("sync") => BARRIER, + BarrierWaitResult("sync") => BARRIERWAITRESULT, + HashMap("collection") => HASHMAP, + HashSet("collection") => HASHSET, + Instant("time") => INSTANT, + LazyLock("sync") => LAZYLOCK, + LockResult("sync") => LOCKRESULT, + Mutex("sync") => MUTEX, + MutexGuard("sync") => MUTEXGUARD, + Once("sync")=> ONCE, + OnceLock("sync") => ONCELOCK, + OnceState("sync") => ONCESTATE, + PoisonError("sync") => POISONERROR, + RwLock("sync") => RWLOCK, + RwLockReadGuard("sync") => RWLOCKREADGUARD, + RwLockWriteGuard("sync") => RWLOCKWRITEGUARD, + SyncCell("sync") => SYNCCELL, + SyncUnsafeCell("cell") => SYNCUNSAFECELL, + TryLockError("sync") => TRYLOCKERROR, + TryLockResult("sync") => TRYLOCKRESULT, } diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs index 648d10c5..a3bd2c07 100644 --- a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs @@ -4,4 +4,7 @@ fn main() { let _ = std::time::Instant::now(); + //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` + //~| HELP: the type `std::time::Instant` can be replaced with the `no_std` compatible type + // bevy_platform::time::Instant } diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr new file mode 100644 index 00000000..15c0ac97 --- /dev/null +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr @@ -0,0 +1,15 @@ +error: Used type from the `std` that has an existing alternative from `bevy_platform` + --> tests/ui/bevy_platform_alternative_exists/main.rs:6:13 + | +6 | let _ = std::time::Instant::now(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: the type `std::time::Instant` can be replaced with the `no_std` compatible type bevy_platform::time::Instant +note: the lint level is defined here + --> tests/ui/bevy_platform_alternative_exists/main.rs:3:9 + | +3 | #![deny(bevy::bevy_platform_alternative_exists)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 6156c1e95ad6b81e66227d4e0ba48147b099280f Mon Sep 17 00:00:00 2001 From: DaAlbrecht Date: Sun, 12 Oct 2025 16:44:29 +0200 Subject: [PATCH 6/7] fix: wrong platform paths --- .../style/bevy_platform_alternative_exists.rs | 18 ++++++++++-------- .../main.fixed | 11 +++++++++++ .../bevy_platform_alternative_exists/main.rs | 7 ++++--- .../main.stderr | 12 ++++++++---- 4 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed diff --git a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs index ff1558a3..8529e442 100644 --- a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs +++ b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_help, source::snippet, ty::ty_from_hir_ty}; +use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet, ty::ty_from_hir_ty}; +use rustc_errors::Applicability; use rustc_lint::{LateContext, LateLintPass}; use crate::{declare_bevy_lint, declare_bevy_lint_pass}; @@ -28,17 +29,18 @@ impl<'tcx> LateLintPass<'tcx> for BevyPlatformAlternativeExists { // Check if for the given `ty` an alternative from `bevy_platform` exists. if let Some(bevy_platform_alternative) = BevyPlatformType::try_from_ty(cx, ty) { - span_lint_and_help( + span_lint_and_sugg( cx, BEVY_PLATFORM_ALTERNATIVE_EXISTS, hir_ty.span, BEVY_PLATFORM_ALTERNATIVE_EXISTS.desc, - None, format!( "the type `{}` can be replaced with the `no_std` compatible type {}", snippet(cx.tcx.sess, hir_ty.span, ""), bevy_platform_alternative.full_path() ), + bevy_platform_alternative.full_path().to_string(), + Applicability::MachineApplicable, ); } } @@ -52,8 +54,8 @@ impl<'tcx> LateLintPass<'tcx> for BevyPlatformAlternativeExists { /// declare_bevy_platform_types! { /// // The variant name => [`PathLookup`] that matches the equivalent type in the std. /// CustomType => CUSTOMTYPE, -/// // Optional the module path can be passed too, default is `bevy_platform::`. -/// // If an additional module path is added, it will result in: `bevy_platform::custom::thread::CustomType`. +/// // Optional the module path can be passed too, default is `bevy::platform::`. +/// // If an additional module path is added, it will result in: `bevy::platform::custom::thread::CustomType`. /// CustomType("custom::thread") => BARRIER, /// ``` macro_rules! declare_bevy_platform_types { @@ -87,7 +89,7 @@ macro_rules! declare_bevy_platform_types { ///Returns a string identifying this [`BevyPlatformType`]. This string is suitable for user output. pub const fn full_path(&self) -> &'static str { match self { - $(Self::$variant => concat!("bevy_platform", $("::", $mod_path,)? "::" , stringify!($variant)),)+ + $(Self::$variant => concat!("bevy::platform", $("::", $mod_path,)? "::" , stringify!($variant)),)+ } } } @@ -97,8 +99,8 @@ macro_rules! declare_bevy_platform_types { declare_bevy_platform_types! { Barrier("sync") => BARRIER, BarrierWaitResult("sync") => BARRIERWAITRESULT, - HashMap("collection") => HASHMAP, - HashSet("collection") => HASHSET, + HashMap("collections") => HASHMAP, + HashSet("collections") => HASHSET, Instant("time") => INSTANT, LazyLock("sync") => LAZYLOCK, LockResult("sync") => LOCKRESULT, diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed new file mode 100644 index 00000000..4ea6939b --- /dev/null +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed @@ -0,0 +1,11 @@ +#![feature(register_tool)] +#![register_tool(bevy)] +#![deny(bevy::bevy_platform_alternative_exists)] + +fn main() { + let mut bar = bevy::platform::collections::HashMap::new(); + //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` + //~| HELP: the type `std::collections::HashMap` can be replaced with the `no_std` compatible + // type bevy::platform::collections::HashMap + bar.insert("foo", "bar"); +} diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs index a3bd2c07..14e60afd 100644 --- a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs @@ -3,8 +3,9 @@ #![deny(bevy::bevy_platform_alternative_exists)] fn main() { - let _ = std::time::Instant::now(); + let mut bar = std::collections::HashMap::new(); //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` - //~| HELP: the type `std::time::Instant` can be replaced with the `no_std` compatible type - // bevy_platform::time::Instant + //~| HELP: the type `std::collections::HashMap` can be replaced with the `no_std` compatible + // type bevy::platform::collections::HashMap + bar.insert("foo", "bar"); } diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr index 15c0ac97..38aeef5a 100644 --- a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr @@ -1,15 +1,19 @@ error: Used type from the `std` that has an existing alternative from `bevy_platform` - --> tests/ui/bevy_platform_alternative_exists/main.rs:6:13 + --> tests/ui/bevy_platform_alternative_exists/main.rs:6:19 | -6 | let _ = std::time::Instant::now(); - | ^^^^^^^^^^^^^^^^^^ +6 | let mut bar = std::collections::HashMap::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the type `std::time::Instant` can be replaced with the `no_std` compatible type bevy_platform::time::Instant note: the lint level is defined here --> tests/ui/bevy_platform_alternative_exists/main.rs:3:9 | 3 | #![deny(bevy::bevy_platform_alternative_exists)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: the type `std::collections::HashMap` can be replaced with the `no_std` compatible type bevy::platform::collections::HashMap + | +6 - let mut bar = std::collections::HashMap::new(); +6 + let mut bar = bevy::platform::collections::HashMap::new(); + | error: aborting due to 1 previous error From eeb34dc6bf69d5351797ba0210b4f1cc81470769 Mon Sep 17 00:00:00 2001 From: DaAlbrecht Date: Mon, 13 Oct 2025 22:45:59 +0200 Subject: [PATCH 7/7] feat: try to narrow down the type definition --- .../style/bevy_platform_alternative_exists.rs | 18 +++++++-- .../main.fixed | 21 +++++++++- .../bevy_platform_alternative_exists/main.rs | 23 ++++++++++- .../main.stderr | 40 ++++++++++++------- 4 files changed, 81 insertions(+), 21 deletions(-) diff --git a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs index 8529e442..4bc2d74c 100644 --- a/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs +++ b/bevy_lint/src/lints/style/bevy_platform_alternative_exists.rs @@ -1,5 +1,6 @@ use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet, ty::ty_from_hir_ty}; use rustc_errors::Applicability; +use rustc_hir::{QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use crate::{declare_bevy_lint, declare_bevy_lint_pass}; @@ -24,11 +25,22 @@ impl<'tcx> LateLintPass<'tcx> for BevyPlatformAlternativeExists { return; } + let as_unambig_ty = hir_ty.as_unambig_ty(); + // lower the [`hir::Ty`] to a [`rustc_middle::ty::Ty`] - let ty = ty_from_hir_ty(cx, hir_ty.as_unambig_ty()); + let ty = ty_from_hir_ty(cx, as_unambig_ty); + + // Get the path to the type definition. + let TyKind::Path(QPath::Resolved(_, path)) = &as_unambig_ty.kind else { + return; + }; - // Check if for the given `ty` an alternative from `bevy_platform` exists. - if let Some(bevy_platform_alternative) = BevyPlatformType::try_from_ty(cx, ty) { + // if for the given `ty` an alternative from `bevy_platform` exists. + if let Some(bevy_platform_alternative) = BevyPlatformType::try_from_ty(cx, ty) + // Only emit a lint if the first segment of this path is `std` thus the type originates + // from the standart library. This prevents linting for `bevy::platform` types that are just a reexport of the `std`. + && path.segments.first().is_some_and(|segment| segment.ident.name.as_str().starts_with("std")) + { span_lint_and_sugg( cx, BEVY_PLATFORM_ALTERNATIVE_EXISTS, diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed index 4ea6939b..a21c8430 100644 --- a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.fixed @@ -2,10 +2,27 @@ #![register_tool(bevy)] #![deny(bevy::bevy_platform_alternative_exists)] +#[allow(dead_code)] +struct Player { + attack_cd: bevy::platform::time::Instant, + //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` + //~| HELP: the type `std::time::Instant` can be replaced with the `no_std` compatible + // type bevy::platform::time::Instant +} + fn main() { - let mut bar = bevy::platform::collections::HashMap::new(); + let mut hash_map = bevy::platform::collections::HashMap::new(); //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` //~| HELP: the type `std::collections::HashMap` can be replaced with the `no_std` compatible // type bevy::platform::collections::HashMap - bar.insert("foo", "bar"); + hash_map.insert("foo", "bar"); + + let _time = bevy::platform::time::Instant::now(); + //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` + //~| HELP: the type `std::time::Instant` can be replaced with the `no_std` compatible + // type bevy::platform::time::Instant + + // This should be fine even tho it will result in a `std::time::Instant` after full path + // resolution. + let _bevy_time = bevy::platform::time::Instant::now(); } diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs index 14e60afd..fa7948b0 100644 --- a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.rs @@ -2,10 +2,29 @@ #![register_tool(bevy)] #![deny(bevy::bevy_platform_alternative_exists)] +use std::time; + +#[allow(dead_code)] +struct Player { + attack_cd: time::Instant, + //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` + //~| HELP: the type `std::time::Instant` can be replaced with the `no_std` compatible + // type bevy::platform::time::Instant +} + fn main() { - let mut bar = std::collections::HashMap::new(); + let mut hash_map = std::collections::HashMap::new(); //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` //~| HELP: the type `std::collections::HashMap` can be replaced with the `no_std` compatible // type bevy::platform::collections::HashMap - bar.insert("foo", "bar"); + hash_map.insert("foo", "bar"); + + let _time = std::time::Instant::now(); + //~^ ERROR: Used type from the `std` that has an existing alternative from `bevy_platform` + //~| HELP: the type `std::time::Instant` can be replaced with the `no_std` compatible + // type bevy::platform::time::Instant + + // This should be fine even tho it will result in a `std::time::Instant` after full path + // resolution. + let _bevy_time = bevy::platform::time::Instant::now(); } diff --git a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr index 38aeef5a..6555bc81 100644 --- a/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr +++ b/bevy_lint/tests/ui/bevy_platform_alternative_exists/main.stderr @@ -1,19 +1,31 @@ error: Used type from the `std` that has an existing alternative from `bevy_platform` - --> tests/ui/bevy_platform_alternative_exists/main.rs:6:19 - | -6 | let mut bar = std::collections::HashMap::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | + --> tests/ui/bevy_platform_alternative_exists/main.rs:16:24 + | +16 | let mut hash_map = std::collections::HashMap::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | note: the lint level is defined here - --> tests/ui/bevy_platform_alternative_exists/main.rs:3:9 - | -3 | #![deny(bevy::bevy_platform_alternative_exists)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> tests/ui/bevy_platform_alternative_exists/main.rs:3:9 + | + 3 | #![deny(bevy::bevy_platform_alternative_exists)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the type `std::collections::HashMap` can be replaced with the `no_std` compatible type bevy::platform::collections::HashMap - | -6 - let mut bar = std::collections::HashMap::new(); -6 + let mut bar = bevy::platform::collections::HashMap::new(); - | + | +16 - let mut hash_map = std::collections::HashMap::new(); +16 + let mut hash_map = bevy::platform::collections::HashMap::new(); + | -error: aborting due to 1 previous error +error: Used type from the `std` that has an existing alternative from `bevy_platform` + --> tests/ui/bevy_platform_alternative_exists/main.rs:22:17 + | +22 | let _time = std::time::Instant::now(); + | ^^^^^^^^^^^^^^^^^^ + | +help: the type `std::time::Instant` can be replaced with the `no_std` compatible type bevy::platform::time::Instant + | +22 - let _time = std::time::Instant::now(); +22 + let _time = bevy::platform::time::Instant::now(); + | + +error: aborting due to 2 previous errors