Consider adding support for identifier aliases
Over in #311, @oovm points out that the fact that components broadly include identifiers in their public interfaces means that it's hard to fix naming mistakes in stable APIs.
I wonder if it might make sense to explicitly support aliases for identifiers in all or most positions to address this: for interface, type, and function names, but ideally also for parameter and return value names.
I think a good way to integrate this would be to introduce a specific structured annotation for aliasing, and support that in all places where an identifier is allowed.
Bindings generators could then use these annotations to generate bindings for all the aliases, and have them use the original identifier internally.
(And if we want to fix a naming mistake, we could maybe do so by changing the name, but introducing an alias for the old name.)
I wrote a simple spell check tool: wit-spell-check
This is the inspection result:
- parameter may wrong:
timestamp- in function
[method]descriptor.set-times - in interface
types - in package
wasi:[email protected] - perhaps ["time stamp", "time-stamp", "times tamp", "times-tamp", "pastime"]
- in function
- parameter may wrong:
timestamp- in function
[method]descriptor.set-times - in interface
types - in package
wasi:[email protected] - perhaps ["time stamp", "time-stamp", "times tamp", "times-tamp", "pastime"]
- in function
- parameter may wrong:
timestamp- in function
[method]descriptor.set-times-at - in interface
types - in package
wasi:[email protected] - perhaps ["time stamp", "time-stamp", "times tamp", "times-tamp", "pastime"]
- in function
- parameter may wrong:
timestamp- in function
[method]descriptor.set-times-at - in interface
types - in package
wasi:[email protected] - perhaps ["time stamp", "time-stamp", "times tamp", "times-tamp", "pastime"]
- in function
- parameter may wrong:
param- in function
[static]response-outparam.set - in interface
types - in package
wasi:[email protected] - perhaps ["para", "pram", "paras", "pa ram", "pa-ram", "par am", "par-am", "para m", "rampart"]
- in function
- parameter may wrong:
len- in function
[method]input-stream.read - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
len- in function
[method]input-stream.blocking-read - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
len- in function
[method]input-stream.skip - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
len- in function
[method]input-stream.blocking-skip - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
len- in function
[method]output-stream.write-zeroes - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
len- in function
[method]output-stream.blocking-write-zeroes-and-flush - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
src- in function
[method]output-stream.splice - in interface
streams - in package
wasi:[email protected] - perhaps ["arc", "sec", "sic", "sac", "soc", "SRO"]
- in function
- parameter may wrong:
len- in function
[method]output-stream.splice - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
src- in function
[method]output-stream.blocking-splice - in interface
streams - in package
wasi:[email protected] - perhaps ["arc", "sec", "sic", "sac", "soc", "SRO"]
- in function
- parameter may wrong:
len- in function
[method]output-stream.blocking-splice - in interface
streams - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
len- in function
get-insecure-random-bytes - in interface
insecure - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
len- in function
get-random-bytes - in interface
random - in package
wasi:[email protected] - perhaps ["Len", "ken", "en", "lens", "lien", "lean", "lent", "lend", "glen", "Olen", "Glen", "lee", "sen", "lei", "lea"]
- in function
- parameter may wrong:
datagrams- in function
[method]outgoing-datagram-stream.send - in interface
udp - in package
wasi:[email protected] - perhaps ["data grams", "data-grams", "grandams"]
- in function
Once things are immutably standardized, I could perhaps see this idea making sense as a way to avoid breaking changes while fixing names. Given that breaking source code is still a breaking change, we'd have to think through carefully how such aliases interact with semver. But in a pre-1.0 timeframe, since we're definitely allowing ourselves to make breaking changes, it seems simpler to just improve the names in each 0.x release (which will be trivial to adapt via component wrapping+re-exporting/importing), and then consider this feature in the lead up to stable 1.0.
This mechanism is very common in serialization frameworks. Serialization must ensure that messages sent by previous versions are still valid, so the rename mechanism is widely used.
- unity: FormerlySerializedAs
- rust: serde.alias
But in a pre-1.0 timeframe, since we're definitely allowing ourselves to make breaking changes, it seems simpler to just improve the names in each 0.x release (which will be trivial to adapt via component wrapping+re-exporting/importing), and then consider this feature in the lead up to stable 1.0.
Oh yeah, I should've emphasized that I don't think we should use a mechanism like this pre-1.0. I was more generally thinking about how to handle this on the long-term.
(Whether we actually want to break arbitrary names in each 0.x release or queue them up for one big 1.0 breakage event is a different question, where I'd slightly lean towards the latter, but that's obviously not a topic to discuss here.)
This is a great discussion! Its really cool to see wit-spell-check, if that tool had existed prior to stabilizing 0.2.0 we probably would have been nudged to turn src and len into source and length. Personally I believe that timestamp and datagrams are good identifiers that are just missing in the dictionary, but we dont need to paint that bikeshed here.
I think there is value in using an aliasing mechanism pre-1.0, which is to make sure that it is supported correctly throughout the ecosystem so that, if we really need to use it in anger post-1.0, its ready for use.