Comment #0 on issue 988 by kimgr: [Feature request] Add "forward" mapping
https://github.com/include-what-you-use/include-what-you-use/issues/988
Yep, something like that would be nice.
I like the idea of a `forward` visibility, but my mind is too cloudy to play out exactly how it would work :-)
I'm mostly typing this up for myself, so I can reason about mappings, I'm not entirely sure this is how it works in practice...
For headers:
* Private-to-private mapping says: "From-header includes to-header, but they are both private"
* Private-to-public mapping says: "From-header is private, to-header is public."
* Public-to-public mapping says: "From-header includes to-header, and they are both public"
* Public-to-private mapping should never exist
The outcome of that is that given a suggested header A;
* if A is public and present, leave it
* if A is public and not present, is there a set of public-to-public mapping from A?
* for every to-header X mapped from A, is X present? If so, leave X.
* if not, suggest A
* if A is private, whether present or not
* if there is a private-to-public mapping from A to X, suggest X
* if not, is there a private-to-private mapping from A to Y? If yes, recurse with Y to see if we can find a public header.
* if no mapping available, suggest A as-is
For symbols, they are just folded into the mapping visibility structure for convenience. The from-visibility is ignored.
* to-private mapping says: "Symbol is defined in to-header, but it is private"
* to-public mapping says: "Symbol is defined in to-header and it is public."
In conjunction with header mappings this can resolve quite nicely. If a symbol is mapped to a private header and private header mapping eventually gives a public header, that strikes a nice balance between ease of generating automated mappings, e.g. `grep` for symbols and map them to their containing file, then `grep` for `#include` directives and generate header mappings. In practice it's not really that simple, of course.
So I wonder if it would be possible to smuggle a `forward-only` visibility into the unused from-visibility field of the symbol mapping... That would still allow to-private and to-public mappings for symbols, but resolution would have to start by deciding whether the symbol we're looking for is for a forward-declare use or a full use. Something like:
Given a used symbol A;
* if it's a forward-declare use, look up mappings for (A, forward-only) and perform resolution as before
* if it's a full use, look up mappings for (A, !forward-only) and perform resolution as before
So rather than tangling that into each mapping, it might make sense to have a separate database of forward-only mappings for symbols. External mapping files could still express it as `{ symbol: [ "std::cout", "forward-only", "<iosfwd>", "public" ] }`, for example, but they could be separated into a dedicated forward-only map when parsing/loading.
I don't know, it doesn't seem very principled, but maybe it doesn't have to be :).
It would be nice with a more structured definition language for mappings and externalization of pragmas. I've started thinking about that a few times, but never finished anything up.