diff --git a/future_form/tests/macro_tests.rs b/future_form/tests/macro_tests.rs index 583c397..861e87c 100644 --- a/future_form/tests/macro_tests.rs +++ b/future_form/tests/macro_tests.rs @@ -276,6 +276,60 @@ mod conditional_bounds { let result = as Debugger>::debug(&wrapper).await; assert_eq!(result, "debugged"); } + + // Multi-letter type params should not be mistaken for variant names + trait MultiLetterParams { + fn process(&self) -> K::Future<'_, String>; + } + + struct MultiLetterContainer { + conn: Conn, + sig: Sig, + } + + #[future_form( + Sendable where + Conn: Clone + Send, + Sig: Clone + Send, + Local where + Conn: Clone, + Sig: Clone + )] + impl MultiLetterParams + for MultiLetterContainer + { + fn process(&self) -> K::Future<'_, String> { + let conn = self.conn.to_string(); + let sig = self.sig.to_string(); + K::from_future(async move { format!("{conn}:{sig}") }) + } + } + + #[tokio::test] + async fn test_multi_letter_type_params_sendable() { + let container = MultiLetterContainer { + conn: "localhost", + sig: "abc123", + }; + let result = + as MultiLetterParams>::process(&container) + .await; + assert_eq!(result, "localhost:abc123"); + } + + #[tokio::test] + async fn test_multi_letter_type_params_local() { + use std::rc::Rc; + let container = MultiLetterContainer { + conn: Rc::from("localhost"), + sig: Rc::from("abc123"), + }; + let result = , Rc> as MultiLetterParams>::process( + &container, + ) + .await; + assert_eq!(result, "localhost:abc123"); + } } mod complex_bounds { diff --git a/future_form_macros/src/lib.rs b/future_form_macros/src/lib.rs index 1f896d0..1ea1f75 100644 --- a/future_form_macros/src/lib.rs +++ b/future_form_macros/src/lib.rs @@ -259,10 +259,14 @@ fn collect_where_clause( // Check if this is a variant name (end of where clause) // Only check at the START of a predicate (not inside a bound) + // Must NOT be followed by `:` (which would make it a type param bound, not a variant) if !in_bound && current_predicate_tokens.is_empty() && let TokenTree::Ident(ident) = token && is_likely_variant(ident) + && !tokens + .get(i + 1) + .is_some_and(|t| matches!(t, TokenTree::Punct(p) if p.as_char() == ':')) { return Ok((predicates, i)); }