From 9dbcd1dcd6177c068f084a9cec032b33c0c87acd Mon Sep 17 00:00:00 2001 From: chrisp60 <89366859+chrisp60@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:04:41 -0400 Subject: [PATCH 1/2] ref: `drain_filter_polyfill` refactors --- Cargo.lock | 7 ----- Cargo.toml | 1 - leptos_macro/src/component.rs | 54 +++++++++++------------------------ leptos_macro/src/slot.rs | 25 ++++++++-------- tachys/Cargo.toml | 1 - tachys/src/view/keyed.rs | 4 +-- 6 files changed, 30 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24ebe402bb..6fae906ca5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1025,12 +1025,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "drain_filter_polyfill" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" - [[package]] name = "either" version = "1.15.0" @@ -3796,7 +3790,6 @@ dependencies = [ "any_spawner", "async-trait", "const_str_slice_concat", - "drain_filter_polyfill", "either_of", "erased", "futures", diff --git a/Cargo.toml b/Cargo.toml index e059b96af7..2f6f639e14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -144,7 +144,6 @@ uuid = { default-features = false, version = "1.18.0" } bytes = { default-features = false, version = "1.10.1" } http = { default-features = false, version = "1.3.1" } regex = { default-features = false, version = "1.11.3" } -drain_filter_polyfill = { default-features = false, version = "0.1.3" } tempfile = { default-features = false, version = "3.23.0" } futures-lite = { default-features = false, version = "2.6.1" } log = { default-features = false, version = "0.4.27" } diff --git a/leptos_macro/src/component.rs b/leptos_macro/src/component.rs index 52e5f6149f..a70d487845 100644 --- a/leptos_macro/src/component.rs +++ b/leptos_macro/src/component.rs @@ -48,20 +48,19 @@ impl Parse for Model { .map(Prop::new) .collect::>(); - // We need to remove the `#[doc = ""]` and `#[builder(_)]` - // attrs from the function signature - drain_filter(&mut item.attrs, |attr| match &attr.meta { - Meta::NameValue(attr) => attr.path == parse_quote!(doc), - Meta::List(attr) => attr.path == parse_quote!(prop), - _ => false, - }); + const DISCARD_ATTRS: &[&str] = &["doc", "prop"]; + + let apply_discard = |attr: &syn::Attribute| { + !DISCARD_ATTRS + .iter() + .any(|discardable| attr.path().is_ident(discardable)) + }; + + item.attrs.retain(apply_discard); + item.sig.inputs.iter_mut().for_each(|arg| { if let FnArg::Typed(ty) = arg { - drain_filter(&mut ty.attrs, |attr| match &attr.meta { - Meta::NameValue(attr) => attr.path == parse_quote!(doc), - Meta::List(attr) => attr.path == parse_quote!(prop), - _ => false, - }); + ty.attrs.retain(apply_discard); } }); @@ -113,22 +112,6 @@ fn maybe_modify_return_type(ret: &mut ReturnType) { } } -// implemented manually because Vec::drain_filter is nightly only -// follows std recommended parallel -pub fn drain_filter( - vec: &mut Vec, - mut some_predicate: impl FnMut(&mut T) -> bool, -) { - let mut i = 0; - while i < vec.len() { - if some_predicate(&mut vec[i]) { - _ = vec.remove(i); - } else { - i += 1; - } - } -} - pub fn convert_from_snake_case(name: &Ident) -> Ident { let name_str = name.to_string(); if !name_str.is_case(Snake) { @@ -668,15 +651,12 @@ pub struct DummyModel { impl Parse for DummyModel { fn parse(input: syn::parse::ParseStream) -> syn::Result { let mut attrs = input.call(Attribute::parse_outer)?; - // Drop unknown attributes like #[deprecated] - drain_filter(&mut attrs, |attr| { - let path = attr.path(); - !(path.is_ident("doc") - || path.is_ident("allow") - || path.is_ident("expect") - || path.is_ident("warn") - || path.is_ident("deny") - || path.is_ident("forbid")) + + const RETAIN_ATTRS: &[&str] = + &["doc", "allow", "expect", "warn", "deny", "forbid"]; + + attrs.retain(|attr| { + RETAIN_ATTRS.iter().any(|known| attr.path().is_ident(known)) }); let vis: Visibility = input.parse()?; diff --git a/leptos_macro/src/slot.rs b/leptos_macro/src/slot.rs index 229afa05cc..3216a3d93f 100644 --- a/leptos_macro/src/slot.rs +++ b/leptos_macro/src/slot.rs @@ -1,5 +1,5 @@ use crate::component::{ - convert_from_snake_case, drain_filter, is_option, unwrap_option, Docs, + convert_from_snake_case, is_option, unwrap_option, Docs, }; use attribute_derive::FromAttr; use proc_macro2::{Ident, TokenStream}; @@ -30,19 +30,18 @@ impl Parse for Model { .map(Prop::new) .collect::>(); - // We need to remove the `#[doc = ""]` and `#[builder(_)]` - // attrs from the function signature - drain_filter(&mut item.attrs, |attr| match &attr.meta { - Meta::NameValue(attr) => attr.path == parse_quote!(doc), - Meta::List(attr) => attr.path == parse_quote!(prop), - _ => false, - }); + const DISCARD_ATTRS: &[&str] = &["doc", "prop"]; + + let apply_discard = |attr: &syn::Attribute| { + !DISCARD_ATTRS + .iter() + .any(|discardable| attr.path().is_ident(discardable)) + }; + + item.attrs.retain(apply_discard); + item.fields.iter_mut().for_each(|arg| { - drain_filter(&mut arg.attrs, |attr| match &attr.meta { - Meta::NameValue(attr) => attr.path == parse_quote!(doc), - Meta::List(attr) => attr.path == parse_quote!(prop), - _ => false, - }); + arg.attrs.retain(apply_discard); }); Ok(Self { diff --git a/tachys/Cargo.toml b/tachys/Cargo.toml index aa75106e38..2fc2341fca 100644 --- a/tachys/Cargo.toml +++ b/tachys/Cargo.toml @@ -148,7 +148,6 @@ web-sys = { features = [ "HtmlTemplateElement", "HtmlOptionElement", ], workspace = true, default-features = true } -drain_filter_polyfill = { workspace = true, default-features = true } indexmap = { workspace = true, default-features = true } rustc-hash = { workspace = true, default-features = true } futures = { workspace = true, default-features = true } diff --git a/tachys/src/view/keyed.rs b/tachys/src/view/keyed.rs index 2278bb2810..14cca81caf 100644 --- a/tachys/src/view/keyed.rs +++ b/tachys/src/view/keyed.rs @@ -8,7 +8,6 @@ use crate::{ renderer::{CastFrom, Rndr}, ssr::StreamBuilder, }; -use drain_filter_polyfill::VecExt as VecDrainFilterExt; use indexmap::IndexSet; use rustc_hash::FxHasher; use std::hash::{BuildHasherDefault, Hash}; @@ -762,8 +761,7 @@ fn apply_diff( children[at] = Some((set_index, item)); } - #[allow(unstable_name_collisions)] - children.drain_filter(|c| c.is_none()); + children.retain(Option::is_some); } fn unpack_moves(diff: &Diff) -> (Vec, Vec) { From 82d7746ae29b19355f64eb9728c0d4d93c335f2b Mon Sep 17 00:00:00 2001 From: chrisp60 <89366859+chrisp60@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:35:45 -0400 Subject: [PATCH 2/2] fix(clippy): unused-imports --- leptos_macro/src/slot.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/leptos_macro/src/slot.rs b/leptos_macro/src/slot.rs index 3216a3d93f..fc8e0677c6 100644 --- a/leptos_macro/src/slot.rs +++ b/leptos_macro/src/slot.rs @@ -5,8 +5,7 @@ use attribute_derive::FromAttr; use proc_macro2::{Ident, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{ - parse::Parse, parse_quote, Field, ItemStruct, LitStr, Meta, Type, - Visibility, + parse::Parse, parse_quote, Field, ItemStruct, LitStr, Type, Visibility, }; pub struct Model {