microsoft / microsoft/windows-rs
`windows-rdl` non-COM interfaces do not support inheritance
- Dominant language
- Rust
- Stars
- 12.8k
- Forks
- 665
- Avg merge
- 7h 9m
- Merged PRs (30d)
- 70
Description
A familiar foe returns: I'm trying to create a compatibility library that binds XAudio 2.7 to XAudio 2.9 for a legacy game.
However, I can't declare a few APIs using the `#[interface]` macro since they derive from `IXAudio2Voice`, which isn't a COM interface.
This is related to #2098 (and other issues/PRs related to that).
For a minimum repro, use the following test (which was modified from `non_com_new.rs`):
```rs
#![allow(non_snake_case, non_camel_case_types)]
use windows::core::*;
// The `interface` macro defines a new local interface that does not derive from `IUnknown` and thus is not a COM interface at all.
#[interface]
unsafe trait IBase {
unsafe fn BaseValue(&self) -> i32;
}
#[interface]
unsafe trait IDerived: IBase {
unsafe fn DerivedValue(&self) -> i32;
}
struct Base(i32);
impl IBase_Impl for Base {
unsafe fn BaseValue(&self) -> i32 {
self.0
}
}
struct Derived(i32, i32);
impl IBase_Impl for Derived {
unsafe fn BaseValue(&self) -> i32 {
self.0
}
}
impl IDerived_Impl for Derived {
unsafe fn DerivedValue(&self) -> i32 {
self.1
}
}
unsafe fn base_value(test: &IBase) -> i32 {
test.BaseValue()
}
unsafe fn derived_value(test: &IDerived) -> i32 {
test.DerivedValue()
}
#[test]
fn base() {
unsafe {
// Since the interface is not rooted in `IUnknown`, there's no COM-style lifetime and the resulting implementation merely
// exists for the lifetime of the referenced implementation.
let test = Base(456);
let interface = IBase::new(&test);
assert_eq!(base_value(&interface), 456);
assert_eq!(interface.BaseValue(), 456);
}
}
#[test]
fn derived() {
unsafe {
let test = Derived(123, 456);
let interface = IDerived::new(&test);
assert_eq!(base_value(&interface), 123);
assert_eq!(interface.BaseValue(), 123);
assert_eq!(derived_value(&interface), 456);
assert_eq!(interface.DerivedValue(), 456);
}
}
```
Specifically, this is the error thrown:
```
error[E0107]: this associated function takes 1 generic argument but 3 generic arguments were supplied
--> crates\tests\interface\tests\non_com_new.rs:11:1
|
11 | #[interface]
| ^^^^^^^^^^^^
| |
| expected 1 generic argument
| help: remove these generic arguments
|
```
Cc @kennykerr (you seem to be the one most familiar with this class of issues)
Contributor guide
Research direction
Start with crates/tests/interface/tests/non_com_new.rs, which contains the minimum reproduction and was modified from the non-COM interface test. Trace the #[interface] macro handling for the IBase and IDerived inheritance shown there. Done means the test compiles and both base and derived method assertions pass without the generic-argument error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100