@@ -112,12 +112,15 @@ impl KotlinMeta {
112112/// [`KotlinMeta::throws_action`].
113113#[ derive( Clone ) ]
114114pub ( crate ) struct ExceptionConfig {
115- /// Absolute Rust path of the error type (e.g.
116- /// `zenoh_flat::errors::ZError`). Used both to splice the
115+ /// Absolute Rust path of the error type, as a `syn::Type::Path`
116+ /// (e.g. `zenoh_flat::errors::ZError`). Used both to splice the
117117 /// `pub(crate) type __JniErr = ...` alias and as the function-
118- /// argument type of the generated `throw_<short>`.
119- pub rust_path : syn:: Path ,
120- /// Last path segment of `rust_path` (e.g. `"ZError"`). Used to
118+ /// argument type of the generated `throw_<short>`. Stored as a
119+ /// `syn::Type` so it round-trips identically with the
120+ /// closure-slot exception bindings in [`WrapperFn`] — both ends
121+ /// spell the type the same way.
122+ pub rust_type : syn:: Type ,
123+ /// Last path segment of `rust_type` (e.g. `"ZError"`). Used to
121124 /// derive the `throw_<short>` function name and to provide the
122125 /// default Kotlin class name when no `.kotlin_name(...)` override
123126 /// is supplied.
@@ -187,7 +190,7 @@ pub(crate) struct TypeConfig {
187190/// composed as a value-inspecting stage onto that converter's chain.
188191/// * `exc` — the bound exception **as a Rust type**, matched by exact
189192/// canonical-form equality against a [`JniExt::kotlin_exception_class`]
190- /// registration's `rust_path ` (use the same full path the
193+ /// registration's `rust_type ` (use the same full path the
191194/// registration was declared with, e.g.
192195/// `parse_quote!(zenoh_flat::errors::ZError)` — no short-name
193196/// matching). `Some(...)` ⇒ throwing: the body evaluates to
@@ -406,7 +409,7 @@ impl JniExt {
406409 /// is called, then auto-rebases via [`Self::recompute_derived`].
407410 pub fn new ( ) -> Self {
408411 let framework_exc = build_exception_config (
409- ":: prebindgen_ext::jni::JniBindingError" ,
412+ syn :: parse_quote! ( :: prebindgen_ext:: jni:: JniBindingError ) ,
410413 "" ,
411414 & [ ] ,
412415 ) ;
@@ -454,19 +457,25 @@ impl JniExt {
454457 /// its own generated Kotlin class and its own `throw_<RustShortName>`
455458 /// free function.
456459 ///
457- /// `rust_path` is the absolute Rust path of the error type (e.g.
458- /// `"zenoh_flat::errors::ZError"`); the type must impl `Display`.
459- /// Bind it to converters by emitting `Some("<rust_path or short>")`
460- /// in the closure's middle slot of [`Self::input_wrapper`] /
461- /// [`Self::output_wrapper`]. The framework's own
460+ /// `rust_type` is the absolute Rust path of the error type as a
461+ /// `syn::Type::Path` (e.g.
462+ /// `parse_quote!(zenoh_flat::errors::ZError)`); the type must impl
463+ /// `Display`. Bind it to converters by emitting
464+ /// `Some(parse_quote!(<same path>))` in the closure's middle slot
465+ /// of [`Self::input_wrapper`] / [`Self::output_wrapper`] — both
466+ /// ends use the same form, matched by exact canonical-form equality
467+ /// (see [`Self::find_exception`]). The framework's own
462468 /// [`crate::jni::JniBindingError`] is pre-registered at
463469 /// `exceptions[0]` for built-in converters; user-declared exceptions
464470 /// land at 1+.
465471 ///
472+ /// Panics when `rust_type` isn't path-shaped (exception classes are
473+ /// always paths; refs, tuples, and generics aren't valid here).
474+ ///
466475 /// The default Kotlin class name is `<package>.<rust_short>`;
467476 /// chain [`Self::kotlin_name`] to override.
468- pub fn kotlin_exception_class ( mut self , rust_path : impl AsRef < str > ) -> Self {
469- let cfg = build_exception_config ( rust_path . as_ref ( ) , & self . package , & self . exceptions ) ;
477+ pub fn kotlin_exception_class ( mut self , rust_type : syn :: Type ) -> Self {
478+ let cfg = build_exception_config ( rust_type , & self . package , & self . exceptions ) ;
470479 self . exceptions . push ( cfg) ;
471480 let idx = self . exceptions . len ( ) - 1 ;
472481 self . last_exception_idx = Some ( idx) ;
@@ -905,7 +914,7 @@ impl JniExt {
905914 /// * `exc = Some(<Rust type>)` ⇒ throwing: `body` evaluates to
906915 /// `Result<ty, <Rust type>>`; framework emits it verbatim. The
907916 /// type must match a [`Self::kotlin_exception_class`] declaration
908- /// by **exact canonical-form equality** with its `rust_path ` (see
917+ /// by **exact canonical-form equality** with its `rust_type ` (see
909918 /// [`Self::find_exception`] — no short-name fallback). The match
910919 /// is validated at lookup time.
911920 ///
@@ -978,14 +987,14 @@ impl JniExt {
978987
979988 /// Resolve an exception type against the registered
980989 /// [`Self::exceptions`] by **exact canonical-form equality** with the
981- /// declaration's `rust_path `. No short-name fallback — the closure /
990+ /// declaration's `rust_type `. No short-name fallback — the closure /
982991 /// caller must spell the same full path
983992 /// `.kotlin_exception_class(...)` was declared with. Returns the
984993 /// index into the `exceptions` vec on match.
985994 fn find_exception ( & self , ty : & syn:: Type ) -> Option < usize > {
986995 let needle = ty. to_token_stream ( ) . to_string ( ) ;
987996 self . exceptions . iter ( ) . position ( |e| {
988- e. rust_path . to_token_stream ( ) . to_string ( ) == needle
997+ e. rust_type . to_token_stream ( ) . to_string ( ) == needle
989998 } )
990999 }
9911000
@@ -1281,15 +1290,16 @@ pub(crate) fn exception_throw_path(exc: &ExceptionConfig) -> syn::Path {
12811290 syn:: Path :: from ( ident)
12821291}
12831292
1284- /// Bare-ident path `__JniErr` — the generated file's alias for the
1293+ /// Bare-ident type `__JniErr` — the generated file's alias for the
12851294/// framework `JniBindingError`. Non-throwing converters use this as
12861295/// their `Result<…, _>` error type so their bodies' `<__JniErr as
12871296/// From<String>>::from(...)` calls keep compiling, and so a
12881297/// `?`-propagated framework failure surfaces as the framework
12891298/// exception on the JVM. Throwing converters bypass this in favour of
1290- /// their bound exception's own path (see [`JniExt::lookup_input`] /
1291- /// [`JniExt::lookup_output`]).
1292- pub ( crate ) fn default_err_path ( ) -> syn:: Path {
1299+ /// their bound exception's own type (see [`JniExt::lookup_input`] /
1300+ /// [`JniExt::lookup_output`]). Returned as `syn::Type` so it shares the
1301+ /// `err_type` binding with [`ExceptionConfig::rust_type`].
1302+ pub ( crate ) fn default_err_type ( ) -> syn:: Type {
12931303 syn:: parse_quote!( __JniErr)
12941304}
12951305
@@ -1317,30 +1327,30 @@ fn validate_path(who: &str, path: &str) -> String {
13171327 path. to_string ( )
13181328}
13191329
1320- /// Construct an [`ExceptionConfig`] from a Rust path string + the
1321- /// current Kotlin package. Shared by [`JniExt::new`] (framework
1330+ /// Construct an [`ExceptionConfig`] from a path-shaped `syn::Type` and
1331+ /// the current Kotlin package. Shared by [`JniExt::new`] (framework
13221332/// `JniBindingError` slot) and [`JniExt::kotlin_exception_class`]
1323- /// (user-declared slots). Panics on invalid input + on collisions
1324- /// against `existing`'s `throw_< short>` names .
1333+ /// (user-declared slots). Panics if `rust_type` isn't a `Type::Path`
1334+ /// or if its short-name collides with an already-registered exception .
13251335fn build_exception_config (
1326- rust_path_str : & str ,
1336+ rust_type : syn :: Type ,
13271337 package : & str ,
13281338 existing : & [ ExceptionConfig ] ,
13291339) -> ExceptionConfig {
1330- let path : syn :: Path = syn :: parse_str ( rust_path_str ) . unwrap_or_else ( |e| {
1331- panic ! (
1332- "kotlin_exception_class: invalid rust path `{}`: {}" ,
1333- rust_path_str , e
1334- )
1335- } ) ;
1336- let short = path
1337- . segments
1340+ let segs = match & rust_type {
1341+ syn :: Type :: Path ( tp ) => & tp . path . segments ,
1342+ _ => panic ! (
1343+ "kotlin_exception_class: expected a path-shaped type, got `{}`" ,
1344+ rust_type . to_token_stream ( )
1345+ ) ,
1346+ } ;
1347+ let short = segs
13381348 . last ( )
13391349 . map ( |s| s. ident . to_string ( ) )
13401350 . unwrap_or_else ( || {
13411351 panic ! (
1342- "kotlin_exception_class: rust path `{}` has no segments" ,
1343- rust_path_str
1352+ "kotlin_exception_class: rust type `{}` has no path segments" ,
1353+ rust_type . to_token_stream ( )
13441354 )
13451355 } ) ;
13461356 let kotlin_fqn = if package. is_empty ( ) {
@@ -1359,7 +1369,7 @@ fn build_exception_config(
13591369 ) ;
13601370 }
13611371 ExceptionConfig {
1362- rust_path : path ,
1372+ rust_type ,
13631373 rust_short : short,
13641374 kotlin_fqn,
13651375 throw_fn_name,
@@ -1431,7 +1441,7 @@ impl JniExt {
14311441 /// * `None` (non-throwing) → signature `Result<rust, __JniErr>` and
14321442 /// the body is wrapped `Ok(<body>)`; `?` inside propagates the
14331443 /// framework error.
1434- /// * `Some(X)` (throwing) → signature `Result<rust, X::rust_path >`
1444+ /// * `Some(X)` (throwing) → signature `Result<rust, X::rust_type >`
14351445 /// and the body is emitted as-is — `<body>` already evaluates to
14361446 /// that `Result`, so no `Ok` wrap (and no cross-type `From`).
14371447 pub ( crate ) fn build_input_fn (
@@ -1444,7 +1454,7 @@ impl JniExt {
14441454 let name = input_name ( rust, wire) ;
14451455 let rust_with_lifetime = annotate_borrow_with_lifetime ( rust, "env" ) ;
14461456 let wire_with_lifetime = annotate_jobject_with_lifetime ( wire, "v" ) ;
1447- let err_type = exc. map ( |e| e. rust_path . clone ( ) ) . unwrap_or_else ( default_err_path ) ;
1457+ let err_type = exc. map ( |e| e. rust_type . clone ( ) ) . unwrap_or_else ( default_err_type ) ;
14481458 let ret_body = body_for_exc ( body, exc) ;
14491459 if matches ! ( wire, syn:: Type :: Ptr ( _) ) {
14501460 syn:: parse_quote!(
@@ -1478,7 +1488,7 @@ impl JniExt {
14781488 ) -> syn:: ItemFn {
14791489 let name = output_name ( rust, wire) ;
14801490 let wire_with_lifetime = annotate_jobject_with_lifetime ( wire, "a" ) ;
1481- let err_type = exc. map ( |e| e. rust_path . clone ( ) ) . unwrap_or_else ( default_err_path ) ;
1491+ let err_type = exc. map ( |e| e. rust_type . clone ( ) ) . unwrap_or_else ( default_err_type ) ;
14821492 let ret_body = body_for_exc ( body, exc) ;
14831493 syn:: parse_quote!(
14841494 #[ allow( non_snake_case, unused_mut, unused_variables, unused_braces, dead_code) ]
@@ -1851,7 +1861,7 @@ impl PrebindgenExt for JniExt {
18511861 // typed `Result<…, X>` — they bypass `__JniErr` entirely so no
18521862 // cross-type bridge between the framework error and a domain
18531863 // error is needed (the orphan rule forbids one).
1854- let error_type = & self . framework_exception ( ) . rust_path ;
1864+ let error_type = & self . framework_exception ( ) . rust_type ;
18551865 let alias: syn:: Item = syn:: parse_quote!(
18561866 #[ allow( dead_code) ]
18571867 pub ( crate ) type __JniErr = #error_type;
0 commit comments