make with_api! take explicit type paths

This commit is contained in:
cyrgani 2026-02-05 12:09:42 +00:00
parent 1a03742c25
commit 18996c6985
3 changed files with 54 additions and 60 deletions

View file

@ -121,7 +121,7 @@ macro_rules! define_client_side {
}
}
}
with_api!(self, define_client_side);
with_api!(define_client_side, TokenStream, Span, Symbol);
struct Bridge<'a> {
/// Reusable buffer (only `clear`-ed, never shrunk), primarily

View file

@ -18,71 +18,67 @@ use crate::{Delimiter, Level};
/// Higher-order macro describing the server RPC API, allowing automatic
/// generation of type-safe Rust APIs, both client-side and server-side.
///
/// `with_api!(MySelf, my_macro)` expands to:
/// `with_api!(my_macro, MyTokenStream, MySpan, MySymbol)` expands to:
/// ```rust,ignore (pseudo-code)
/// my_macro! {
/// fn lit_character(ch: char) -> MySelf::Literal;
/// fn lit_span(lit: &MySelf::Literal) -> MySelf::Span;
/// fn lit_set_span(lit: &mut MySelf::Literal, span: MySelf::Span);
/// fn ts_clone(stream: &MyTokenStream) -> MyTokenStream;
/// fn span_debug(span: &MySpan) -> String;
/// // ...
/// }
/// ```
///
/// The first argument serves to customize the argument/return types,
/// to enable several different usecases:
///
/// If `MySelf` is just `Self`, then the types are only valid inside
/// a trait or a trait impl, where the trait has associated types
/// for each of the API types. If non-associated types are desired,
/// a module name (`self` in practice) can be used instead of `Self`.
/// The second (`TokenStream`), third (`Span`) and fourth (`Symbol`)
/// argument serve to customize the argument/return types that need
/// special handling, to enable several different representations of
/// these types.
macro_rules! with_api {
($S:ident, $m:ident) => {
($m:ident, $TokenStream: path, $Span: path, $Symbol: path) => {
$m! {
fn injected_env_var(var: &str) -> Option<String>;
fn track_env_var(var: &str, value: Option<&str>);
fn track_path(path: &str);
fn literal_from_str(s: &str) -> Result<Literal<$S::Span, $S::Symbol>, ()>;
fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>);
fn literal_from_str(s: &str) -> Result<Literal<$Span, $Symbol>, ()>;
fn emit_diagnostic(diagnostic: Diagnostic<$Span>);
fn ts_drop(stream: $S::TokenStream);
fn ts_clone(stream: &$S::TokenStream) -> $S::TokenStream;
fn ts_is_empty(stream: &$S::TokenStream) -> bool;
fn ts_expand_expr(stream: &$S::TokenStream) -> Result<$S::TokenStream, ()>;
fn ts_from_str(src: &str) -> $S::TokenStream;
fn ts_to_string(stream: &$S::TokenStream) -> String;
fn ts_drop(stream: $TokenStream);
fn ts_clone(stream: &$TokenStream) -> $TokenStream;
fn ts_is_empty(stream: &$TokenStream) -> bool;
fn ts_expand_expr(stream: &$TokenStream) -> Result<$TokenStream, ()>;
fn ts_from_str(src: &str) -> $TokenStream;
fn ts_to_string(stream: &$TokenStream) -> String;
fn ts_from_token_tree(
tree: TokenTree<$S::TokenStream, $S::Span, $S::Symbol>,
) -> $S::TokenStream;
tree: TokenTree<$TokenStream, $Span, $Symbol>,
) -> $TokenStream;
fn ts_concat_trees(
base: Option<$S::TokenStream>,
trees: Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>,
) -> $S::TokenStream;
base: Option<$TokenStream>,
trees: Vec<TokenTree<$TokenStream, $Span, $Symbol>>,
) -> $TokenStream;
fn ts_concat_streams(
base: Option<$S::TokenStream>,
streams: Vec<$S::TokenStream>,
) -> $S::TokenStream;
base: Option<$TokenStream>,
streams: Vec<$TokenStream>,
) -> $TokenStream;
fn ts_into_trees(
stream: $S::TokenStream
) -> Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>;
stream: $TokenStream
) -> Vec<TokenTree<$TokenStream, $Span, $Symbol>>;
fn span_debug(span: $S::Span) -> String;
fn span_parent(span: $S::Span) -> Option<$S::Span>;
fn span_source(span: $S::Span) -> $S::Span;
fn span_byte_range(span: $S::Span) -> Range<usize>;
fn span_start(span: $S::Span) -> $S::Span;
fn span_end(span: $S::Span) -> $S::Span;
fn span_line(span: $S::Span) -> usize;
fn span_column(span: $S::Span) -> usize;
fn span_file(span: $S::Span) -> String;
fn span_local_file(span: $S::Span) -> Option<String>;
fn span_join(span: $S::Span, other: $S::Span) -> Option<$S::Span>;
fn span_subspan(span: $S::Span, start: Bound<usize>, end: Bound<usize>) -> Option<$S::Span>;
fn span_resolved_at(span: $S::Span, at: $S::Span) -> $S::Span;
fn span_source_text(span: $S::Span) -> Option<String>;
fn span_save_span(span: $S::Span) -> usize;
fn span_recover_proc_macro_span(id: usize) -> $S::Span;
fn span_debug(span: $Span) -> String;
fn span_parent(span: $Span) -> Option<$Span>;
fn span_source(span: $Span) -> $Span;
fn span_byte_range(span: $Span) -> Range<usize>;
fn span_start(span: $Span) -> $Span;
fn span_end(span: $Span) -> $Span;
fn span_line(span: $Span) -> usize;
fn span_column(span: $Span) -> usize;
fn span_file(span: $Span) -> String;
fn span_local_file(span: $Span) -> Option<String>;
fn span_join(span: $Span, other: $Span) -> Option<$Span>;
fn span_subspan(span: $Span, start: Bound<usize>, end: Bound<usize>) -> Option<$Span>;
fn span_resolved_at(span: $Span, at: $Span) -> $Span;
fn span_source_text(span: $Span) -> Option<String>;
fn span_save_span(span: $Span) -> usize;
fn span_recover_proc_macro_span(id: usize) -> $Span;
fn symbol_normalize_and_validate_ident(string: &str) -> Result<$S::Symbol, ()>;
fn symbol_normalize_and_validate_ident(string: &str) -> Result<$Symbol, ()>;
}
};
}
@ -146,7 +142,7 @@ macro_rules! declare_tags {
rpc_encode_decode!(enum ApiTags { $($method),* });
}
}
with_api!(self, declare_tags);
with_api!(declare_tags, __, __, __);
/// Helper to wrap associated types to allow trait impl dispatch.
/// That is, normally a pair of impls for `T::Foo` and `T::Bar`

View file

@ -58,7 +58,7 @@ struct Dispatcher<S: Server> {
server: S,
}
macro_rules! define_server_dispatcher_impl {
macro_rules! define_server {
(
$(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
) => {
@ -77,22 +77,20 @@ macro_rules! define_server_dispatcher_impl {
$(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?;)*
}
}
}
with_api!(define_server, Self::TokenStream, Self::Span, Self::Symbol);
macro_rules! define_dispatcher {
(
$(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
) => {
// FIXME(eddyb) `pub` only for `ExecutionStrategy` below.
pub trait DispatcherTrait {
// HACK(eddyb) these are here to allow `Self::$name` to work below.
type TokenStream;
type Span;
type Symbol;
fn dispatch(&mut self, buf: Buffer) -> Buffer;
}
impl<S: Server> DispatcherTrait for Dispatcher<S> {
type TokenStream = MarkedTokenStream<S>;
type Span = MarkedSpan<S>;
type Symbol = MarkedSymbol<S>;
fn dispatch(&mut self, mut buf: Buffer) -> Buffer {
let Dispatcher { handle_store, server } = self;
@ -127,7 +125,7 @@ macro_rules! define_server_dispatcher_impl {
}
}
}
with_api!(Self, define_server_dispatcher_impl);
with_api!(define_dispatcher, MarkedTokenStream<S>, MarkedSpan<S>, MarkedSymbol<S>);
pub trait ExecutionStrategy {
fn run_bridge_and_client(