I'm considering refactoring the ExtInfo
types in the codebase to use a builder-style API. More concretely, the change would look something like:
// Present:
ExtInfo:
- // constructors elided
- getXYZ : ExtInfo -> XYZ
- withXYZ : XYZ -> ExtInfo -> ExtInfo
// Future:
ExtInfoBuilder:
- // constructors elided
- getXYZ : ExtInfoBuilder -> XYZ
- withXYZ : XYZ -> ExtInfoBuilder -> ExtInfoBuilder
- finish : ExtInfoBuilder -> ExtInfo
ExtInfo:
- // no public constructors
- getXYZ : ExtInfo -> XYZ
- rebuild : ExtInfo -> ExtInfoBuilder // (strawman name)
The builder represents a WIP state. In finish
, we check all the fields are in a mutually consistent state (when compiling with assertions enabled). This means that it becomes impossible to safely create an ExtInfo
in an invalid state. This would avoid some complexity in the code today:
static bool isEscaping(Type type) {
if (auto *funcType = type->getAs<AnyFunctionType>()) {
if (funcType->getExtInfo().getRepresentation() ==
FunctionTypeRepresentation::CFunctionPointer)
return false;
return !funcType->getExtInfo().isNoEscape();
}
return false;
}
After this change, we will be able to call funcType->getExtInfo().isNoEscape()
directly without needing to check the representation.
This should also enable us to roll out changes for propagating Clang types through SIL easier; right now, I'm playing whack-a-mole trying to find places creating an ExtInfo but not setting the Clang type field properly.
The implementation would involve ExtInfo
being a single-element struct containing an ExtInfoBuilder
(i.e. it is a newtype wrapper which enforces some extra invariants on top of the internal type).
There are a couple of shortcomings with this:
- It is a bit less ergonomic to use for small changes, now you need
rebuild().withXYZ().finish()
instead ofwithXYZ()
. - There is a little bit of duplication with the getters.
IMO these are acceptable.
Do people have any major concerns with this approach? It might create some merge conflicts in the short term but I think this should be overall a positive for correctness and making future changes easier.