Hi all -- fairly new to posting here so please let me know if additional context / etc. of any sort is needed.
I work on a very large codebase (2M+ lines of code; 50/50 Swift and Obj-C) and at that scale, we have to be very careful with how we shape the dependency structure of modules within the codebase to optimize incremental build times (150+ modules).
One such strategy is the tried-and-true API / Implementation split; we have modules that are strictly "API" modules and contain only protocols and the like. The idea is that the APIs are more stable and change less frequently, whereas the implementation generally changes more frequently. If only the implementation changes, very little code has to be rebuilt other than that implementation because other dependent modules depend on only the corresponding API module.
The tricky part is that we can't make each API module fully independent. For instance, API module A might need to reference a protocol that's defined in API module B. However, if we allow API modules to depend on one another, sooner or later, we'd end up with a web of interdependent module that's equivalent to one "giant" API module, which means that anytime any API module is changed, all API modules need to be rebuilt, which then means close to the entire app has to be rebuilt (since presumably every other module in the app would depend on at least one API module).
The way we solve around this currently is by restricting our API modules so that we can only write them using Objective-C. This is because in Objective-C, we can forward declare types, which means we can avoid having API module A depend on API module B by forward declaring types from API module B in API module A.
So, for example, if I am working in an implementation module X and trying to use an API from API module A that forward declares a type from API module B, I would need to import both API module A and API module B.
This strategy allows good modularization and sane incremental build times. The unfortunate downside is that we can't leverage any Swift-only APIs, beginning with enums with associated types and running up to new frameworks such as Combine / SwiftUI since everything has to able to expressed in Objective-C.
The ask, then, is what are thoughts on adding the ability to leverage forward declarations within Swift to enable an API / Implementation strategy to scale incremental builds for very large codebases? Alternatively, forward declarations doesn't necessarily have to be the solution, though it is the only one that I can think of right now. If there are other solutions or potential evolutions for Swift to solve the same problem, feel free to share!