Closed Boddlnagg closed 6 years ago
This is complicated by the fact that we can't just use Option<ComPtr<...>>
in arrays, at least not without the null-pointer optimization. Option<ComPtr<...>>
must be pointer-sized for that to work.
Alternatively we could change our definition of Result
: We could either define a new result type with three variants (Ok
, None
/Missing
and Err
) or extend the Error
type with a Null
variant. The first one would be closer to the actual semantics of WinRT (because there's a difference between returning null
and actually throwing an error/exception, but returning null
is not really considered an error), but it would mean that we can't just use ::std::result::Result
. I don't know if the latter would be a problem (it might be totally okay now that we can use ?
with custom types).
This is better than Option<ComPtr<...>>
because it doesn't require double-unwrap
(or double-?
) every time I want to access a method's result.
See https://docs.microsoft.com/en-us/uwp/api/windows.storage.istorageitem2#Windows_Storage_IStorageItem2_GetParentAsync for an example of a method where it is explicitly documented that it can return null
.
Another thing: null return values can only happen for interface return values (and HString
s, but we already deal correctly with those), i.e. those types that are currently wrapped in ComPtr<...>
. But not for primitive types (including ()
), structs or enums, obviously. So should we use different Result
types depending on the category of the return type?
An interesting special case might be the async task results. Maybe we can assume that a returned IAsyncOperation<...>
is never null?
Since we can't be sure whether interface return values are never
null
, we probably have to check that and return anOption<ComPtr<...>>
instead. We should try to make use of the null-pointer optimization here, so there will be no unnecessary overhead.