timsaucer commented on code in PR #22797:
URL: https://github.com/apache/datafusion/pull/22797#discussion_r3658076496


##########
.ai/skills/datafusion-ffi/SKILL.md:
##########
@@ -235,7 +235,7 @@ What integration tests catch that unit tests cannot:
 - Primitives (`u8`/`u64`/`bool`/`usize`, etc.) and `#[repr(u8)]` FFI enums 
(`FFI_TableType`, `Volatility`, `InsertOp`, `TableProviderFilterPushDown`).
 - A `stabby::string::String` (`SString`) returned by value, with no other args 
or returns.
 
-Concrete skippable example: `fn name(&self) -> SString` reading a field 
already validated by another method. Concrete *non*-skippable examples: 
anything returning `SVec<T>`, `FFI_Option<T>`, `FFI_Result<T>`, 
`WrappedSchema`, `WrappedArray`, an `FfiFuture`, an `FFI_*` sub-struct, or any 
`*mut`/`*const` pointer — those exercise alignment / padding / niche-opt across 
the ABI boundary and need the two-build coverage. When unsure, write the 
integration test; the cost is one constructor + ~20 lines.
+Concrete skippable example: `fn name(&self) -> SString` reading a field 
already validated by another method. Concrete *non*-skippable examples: 
anything returning `SVec<T>`, `FFI_Option<T>`, `FFI_Result<T>`, 
`WrappedSchema`, `WrappedArray`, an `FfiFuture`, an `FFI_*` sub-struct, or any 
`*mut`/`*const` pointer — those exercise alignment / padding / niche-opt across 
the ABI boundary and need the two-build coverage. When unsure, write the 
integration test and extend an existing fixture first.

Review Comment:
   I think instead of modifying this statement you just want a different 
statement that covers the case you're working on - expanding an existing struct 
that can happen when we're either implementing a default method that wasn't 
done or when new methods get added to a trait.



##########
.ai/skills/datafusion-ffi/SKILL.md:
##########
@@ -209,9 +209,9 @@ cargo test -p datafusion-ffi --features integration-tests
 
 To add coverage for a new wrapper:
 
-1. **Add a constructor** in `src/tests/<area>.rs` (or a new file there). 
Return a populated `FFI_X` from a known-good native type.
-2. **Wire it into `ForeignLibraryModule`** in `src/tests/mod.rs`: add a field 
of type `extern "C" fn(...) -> FFI_X` and populate it in 
`datafusion_ffi_get_module`. This struct is the cross-library contract — adding 
a field is itself an ABI change for the test module; integration tests will 
rebuild the cdylib automatically.
-3. **Add the test** in `tests/ffi_<area>.rs` under `#[cfg(feature = 
"integration-tests")] mod tests { … }`. Call 
`datafusion_ffi::tests::utils::get_module()` to load the cdylib, invoke your 
constructor through the returned `ForeignLibraryModule`, convert into `Arc<dyn 
X>`, and exercise every method.
+1. **Reuse an existing fixture and constructor** when it can express the new 
behaviour with a small trait-method override. Do not add a dedicated test type 
or `ForeignLibraryModule` field for each method.
+2. **Add a constructor only when necessary** in `src/tests/<area>.rs` (or a 
new file there). Return a populated `FFI_X` from a known-good native type, then 
wire it into `ForeignLibraryModule` in `src/tests/mod.rs`.

Review Comment:
   I don't think this captures the right context. This section is describe 
implementing an entirely new FFI struct, right? I think the thing you're doing 
is expanding upon an existing FFI struct.



##########
.ai/skills/datafusion-ffi/SKILL.md:
##########
@@ -313,6 +313,8 @@ If a method's body is non-trivial, the consumer-side 
default is non-trivial too.
 - **Logical `Expr` / `LogicalPlan`**: serialize via `datafusion-proto` using 
the embedded `FFI_LogicalExtensionCodec`. Same for physical plans → 
`FFI_PhysicalExtensionCodec`.
 - **Enums** (`Volatility`, `TableType`, `InsertOp`, 
`TableProviderFilterPushDown`): `#[repr(u8)]`, with `From<Native> for FFI_X` 
and `From<&FFI_X> for Native`. Always write a round-trip unit test that 
exercises every variant.
 - **Errors**: every `FFI_X` method that can fail returns `FFI_Result<T>`. Use 
the `sresult!`, `sresult_return!`, `df_result!` macros from `src/util.rs` — do 
not roll your own.
+- **Infallible trait methods**: if an FFI call can fail but the native trait 
cannot return the error, log the transport error before returning the trait's 
fallback (`None`, `false`, or a default). Never discard it with `.ok()`, 
`.unwrap_or_default()`, or equivalent.
+- **Owned FFI returns**: consume an owned `FFI_X` with `From<FFI_X>` instead 
of converting through `&FFI_X` and cloning across the boundary. Keep the 
borrowed conversion's local marker fast path.

Review Comment:
   Can you remind me where this came up?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to