Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WinRT noexcept support #3070

Merged
merged 11 commits into from
Jun 7, 2024
Merged

Add WinRT noexcept support #3070

merged 11 commits into from
Jun 7, 2024

Conversation

kennykerr
Copy link
Collaborator

@kennykerr kennykerr commented Jun 5, 2024

A few years ago, I introduced an optimization for https://github.com/microsoft/cppwinrt that allowed methods and properties to be attributed as noexcept to improve call site code generation. While all WinRT methods must return an HRESULT on the ABI, noexcept methods always return S_OK and are thus infallible. This does not change the way C++ code "looks and feels" but C++/WinRT would mark such methods noexcept in the C++ sense which allows the C++ compiler to avoid a bunch of exception handling overhead at call sites, reducing code size.

In Rust, the noexcept can further be used to avoid having to unwrap method calls that are known to be infallible. This also reduces error handling overhead but additionally simplifies implementations and call sites as method return values may be used directly without unwrapping.

The test included with this update illustrates the impact of this change. Consider the following IDL definition of an interface:

namespace Test
{
    interface ITest
    {
        void MethodString(String test);
        void MethodInt32(Int32 test);
        void MethodTest(ITest test);
        String String;
        Int32 Int32;
        ITest Test;

        [noexcept] void MethodStringN(String test);
        [noexcept] void MethodInt32N(Int32 test);
        [noexcept] void MethodTestN(ITest test);
        [noexcept] String StringN;
        [noexcept] Int32 Int32N;
        [noexcept] ITest TestN;
    }
}

In Rust, the first batch of methods all return a Result while the second do not:

#[test]
fn test_except() -> Result<()> {
    let test: ITest = Test::default().into();

    test.MethodString(h!("abc"))?;
    assert_eq!(test.String()?, "abc");

    test.MethodInt32(123)?;
    assert_eq!(test.Int32()?, 123);

    test.MethodTest(&test)?;
    assert_eq!(&test.Test()?, &test);

    Ok(())
}

#[test]
fn test_noexcept() {
    let test: ITest = Test::default().into();

    test.MethodStringN(h!("abc"));
    assert_eq!(test.StringN(), "abc");

    test.MethodInt32N(123);
    assert_eq!(test.Int32N(), 123);

    test.MethodTestN(&test);
    assert_eq!(test.TestN().as_ref(), Some(&test));
}

Fixes: #2991

eholk
eholk previously approved these changes Jun 5, 2024
@kennykerr
Copy link
Collaborator Author

7dfe20b adds interop testing against C++/WinRT.

@kennykerr kennykerr merged commit 21d17ab into master Jun 7, 2024
90 checks passed
@kennykerr kennykerr deleted the noexcept2 branch June 7, 2024 00:07
mati865 pushed a commit to mati865/windows-rs that referenced this pull request Jun 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add noexcept support for WinRT methods/properties
5 participants