https://github.com/microsoft/windows-rs/pull/587 introduced a change which dramatically reduced the amount of code being generated for a given set of types. This is largely a step in the direction, but it is potentially a bit too aggressive.
When generating types using the build! macro, only the types specified will be generated. If for example we specify type T1, T1 itself will be generated, but T1's methods which refer to other types which were not specified will not be generated. In other words, if T1 has a method m1 which takes a T2, but T2 was not specified in the build! macro, m1 will not be generated at all.
This can cause confusion since the docs specify that T1 has a method named m1. The user must know that it is not generated because of a missing dependency.
This is only the case for dependencies of a certain WinRT and COM types' methods and not of other types like free standing functions, structs, delegates, etc and not for these types static methods. Such types will always be generated and cause their arguments and return types to be generated.
There are several ways to fix this issue, but here is a suggestion we can use to kick off conversation:
When generating a COM or WinRT type, generate all methods for such types. For the argument and return types which are not already generated dependencies, generate a simple unit struct with that types name. Wrap these argument types in an NotGenerated<T> struct where T is the unit struct that was just generated. Ideally NotGenerated<T> would be impossible for users to construct such that it would not be possible to call a method with unimplemented method arguments.
For example, in the case illustrated above, we would generate T1::m1 but its argument would be NotGenerated<T2>.
This should give a clear indication to the user that the type in question is not generated and that they need to do so. While this solution still requires the user to connect the dots between an NotGenerated<T> and the build! macro, this is an improvement over the silent "failure" that currently exists.
I'm working on this now. It's a little complicated but I think we can make this a lot more user-friendly.
As part of implementing #81 its gotten a little more complicated when implementing or extending WinRT types as the caller must be able to implement exclusive interfaces, which are trimmed by the dependency tracker by default. This is not something the dependency tracker could predict, unless perhaps it includes such dependencies based on the inclusion of the macros feature that enables the macros like implement. Probably not very effective as the macros feature gates both the build macro (used by everyone) and the implement macro (used by few). So that solution would likely only be effective once we have #432.
Here's an example of how it ends up missing necessary type definitions: https://github.com/microsoft/windows-rs/issues/823#issuecomment-849081098
I think what I'll do is move the dependency tracker from a binary model (type is either present or missing) to a model where a type is fully-defined, minimally-defined, or missing. This is closer to the model used by C++/WinRT to deal with indirect dependencies. In this model, no methods are omitted from types that are imported directly but methods will be omitted from types that are only included to satisfy method declarations. This should be far less confusing and also avoid the issues with the implement macro requiring complete type definitions. It will mean more code gen in some cases, but the gain in usability seems worthwhile.
Most helpful comment
Here's an example of how it ends up missing necessary type definitions: https://github.com/microsoft/windows-rs/issues/823#issuecomment-849081098
I think what I'll do is move the dependency tracker from a binary model (type is either present or missing) to a model where a type is fully-defined, minimally-defined, or missing. This is closer to the model used by C++/WinRT to deal with indirect dependencies. In this model, no methods are omitted from types that are imported directly but methods will be omitted from types that are only included to satisfy method declarations. This should be far less confusing and also avoid the issues with the
implementmacro requiring complete type definitions. It will mean more code gen in some cases, but the gain in usability seems worthwhile.