<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div class="markdown-here-wrapper" data-md-url="" style="" markdown-here-wrapper-content-modified="true">
<p style="margin: 0px 0px 1.2em !important;">Hi all,<br>
we tried mainly three approaches to allow smoother interop
between strings and string templates: (a) make String a subclass
of StringTemplate. Or (b) make constant strings bs <em>convertible</em>
to string templates. Or, (c) use target-typing. All these
approaches have some issues, discussed below.<br>
</p>
<p style="margin: 0px 0px 1.2em !important;">The first approach is
slightly simpler, because it can be achieved entirely outside of
the Java language. Unfortunately, adding “String implements
StringTemplate” adds overload ambiguities in cases such as this:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">format(StringTemplate) // 1
format(String, Object...) // 2
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">This is actually a
very important case, as we predice that StringTemplate will
serve as a great replacement for methods out there accepting a
string/Object… pack.</p>
<p style="margin: 0px 0px 1.2em !important;">Unfortunatly, if
String <: StringTemplate, this means that calling format with
a string literal will resolve to (1), not (2) as before. The
problem here is that (2) is not even applicable during the two
overload resolution phases (which is only allowed to use
subtyping and conversions, respectively), as it is a varargs
method. Because of this, (1) will now take the precedence, as
that’s not varargs. While for String::format this is probably
harmless, changing results of overload selection is something
that should be done with care (esp. if different overloads have
different return types), as it could lead to source
compatibility issues.</p>
<p style="margin: 0px 0px 1.2em !important;">On top of these
issues, making all strings be string templates has the
disadvantage of also considering “messy” strings obtained via
concatenation of non-constant values string templates too, which
seems bad.</p>
<p style="margin: 0px 0px 1.2em !important;">To overcome these
issues, we attempetd to add an implicit conversion from <em>constant</em>
strings to StringTemplate. As it was observed by Guy, in case of
ambiguities, the non-converting variants (e.g. m(String)) would
be preferred. That said, in the above example (with varargs) we
would still get a potentially incompatible change - as a string
literal would be applicable in (1) before (2) is even
considered, so the same concerns surrounding overload resolution
changes would remain.</p>
<p style="margin: 0px 0px 1.2em !important;">Another thing that
came up is that conversions automatically bring in casting
conversions. E.g. if you can go from A to B using assignment
conversion, you can typically go the same direction using
casting conversion. This raises two issues. The first is that
casting conversion is generally a symmetric type relationship
(e.g. if you can cast from A to B, then you can cast from B to
A), while here we’re mostly discussing about one direction. But
this is, perhaps, not a big deal - after all, “constant strings”
don’t have a denotable type, so perhaps it should come to no
surprise that you can’t use them as a <em>target</em> type for
a cast.</p>
<p style="margin: 0px 0px 1.2em !important;">The second “issue” is
that casting conversion brings about patterns, as that’s how
pattern applicability is defined. For instance:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">switch("Hello") {
case StringTemplate st ...
}
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">To make this work we
would need at least to tweak exhaustiveness (otherwise javac
would think the above switch is not exhaustive, and ask you to
add a default). Secondly, some tweaks to the runtime tests would
be required also. Not impossible, but would require some more
work to make sure we’re ok with this direction.</p>
<p style="margin: 0px 0px 1.2em !important;">Another issue with
the conversion is that it would expose a sharp edge in the
current overload resolution and inference machinery. For
instance, this program doesn’t compile correctly:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"> List<Integer> li = List.of(1, 1L)
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">Similarly, this
program would also not compile correctly:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"> List<StringTemplate> li = List.of("Hello", "Hello \{world}");
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">The last possibility
would be to say that a string literal is a <em>poly expression</em>.
As such, a string literal can be typed to either String or
StringTemplate depending on the target type (for instance, this
is close to how int literals also work).</p>
<p style="margin: 0px 0px 1.2em !important;">This approach would
still suffer from the same incompatible overload changes with
varargs method as the other approaches. But, by avoiding to add
a conversion, it makes things a little easier: for instance, in
the case of pattern matching, nothing needs to be done, as the
string literal will be turned into a string template <em>before</em>
the switch even takes place (meaning that existing
exhaustiveness and runtime checks would still work). But,
there’s still dragons and irregularities when it comes to
inference - for instance:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">List<StringTemplate> lst = List.of("hello", "world");
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">This would not
type-check: we need a target-type to know which way the literal
is going (List::of just accepts a type-variable X). Note that
overload resolution happens at a time where the target-type is
not known, so here we’d probably pick X = String, which will
then fail to type-check against the target.</p>
<p style="margin: 0px 0px 1.2em !important;">Another issue with
target-typing is that if you have two overloads:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">m(String)
m(StringTemplate)
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">And you call this
with a string literal, you get an ambiguity: you can go both
ways, but String and StringTemplate are unrelated types, so we
can’t pick one as “most specific”. This issue could be
addressed, in principle, by adding an ad-hoc most specific rule
that, in case of an ambiguity, always gave precedence to String
over StringTemplate. We do a similar trick for lambda
expressions, where if two method accepts similarly looking
functional interface, we give precedence to the non-boxing one.</p>
<p style="margin: 0px 0px 1.2em !important;">Anyway, the general
message here is that it’s a bit of a “pick your posion”
situation. Adding a more fluid relationship between string and
templates is definitively possible, but there are risks that
this will impact negatively other areas of the language, risks
that would need to be assessed very carefully.</p>
<p style="margin: 0px 0px 1.2em !important;">Another, simpler,
option we consider was to use some kind of prefix to mark a
string template literal (e.g. make that explicit, instead of
resorting to language wizardry). That works, but has the
disadvantage of breaking the spell that there is only “one
string literal”, which is something we have worked quite hard to
achieve.</p>
<p style="margin: 0px 0px 1.2em !important;">Cheers<br>
Maurizio</p>
<p style="margin: 0px 0px 1.2em !important;">On 09/03/2024 23:52,
Brian Goetz wrote:</p>
<p style="margin: 0px 0px 1.2em !important;"></p>
<div class="markdown-here-exclude">
<p></p>
<blockquote type="cite" cite="mid:B6E205D1-C0BE-4506-A06C-7DF03A3910C1@oracle.com">
<pre>I’ll let Maurizio give the details, because I’m sure I will have forgotten one or two.
</pre>
</blockquote>
<p></p>
</div>
<p style="margin: 0px 0px 1.2em !important;"></p>
<div title="MDH:PHA+SGkgYWxsLDxicj53ZSB0cmllZCBtYWlubHkgdGhyZWUgYXBwcm9hY2hlcyB0byBhbGxvdyBz
bW9vdGhlciBpbnRlcm9wIGJldHdlZW4gc3RyaW5ncyBhbmQgc3RyaW5nIHRlbXBsYXRlczogKGEp
IG1ha2UgU3RyaW5nIGEgc3ViY2xhc3Mgb2YgU3RyaW5nVGVtcGxhdGUuIE9yIChiKSBtYWtlIGNv
bnN0YW50IHN0cmluZ3MgYnMgX2NvbnZlcnRpYmxlXyB0byBzdHJpbmcgdGVtcGxhdGVzLiBPciwg
KGMpIHVzZSB0YXJnZXQtdHlwaW5nLjxicj48L3A+PHA+VGhlIGZpcnN0IGFwcHJvYWNoIGlzIHNs
aWdodGx5IHNpbXBsZXIsIGJlY2F1c2UgaXQgY2FuIGJlIGFjaGlldmVkIGVudGlyZWx5IG91dHNp
ZGUgb2YgdGhlIEphdmEgbGFuZ3VhZ2UuIFVuZm9ydHVuYXRlbHksIGFkZGluZyAiU3RyaW5nIGlt
cGxlbWVudHMgU3RyaW5nVGVtcGxhdGUiIGFkZHMgb3ZlcmxvYWQgYW1iaWd1aXRpZXMgaW4gY2Fz
ZXMgc3VjaCBhcyB0aGlzOjwvcD48cD5gYGA8YnI+Zm9ybWF0KFN0cmluZ1RlbXBsYXRlKSAvLyAx
PGJyPmZvcm1hdChTdHJpbmcsIE9iamVjdC4uLikgLy8gMjxicj5gYGA8YnI+PC9wPjxwPlRoaXMg
aXMgYWN0dWFsbHkgYSB2ZXJ5IGltcG9ydGFudCBjYXNlLCBhcyB3ZSBwcmVkaWNlIHRoYXQgU3Ry
aW5nVGVtcGxhdGUgd2lsbCBzZXJ2ZSBhcyBhIGdyZWF0IHJlcGxhY2VtZW50IGZvciBtZXRob2Rz
IG91dCB0aGVyZSBhY2NlcHRpbmcgYSBzdHJpbmcvT2JqZWN0Li4uIHBhY2suPC9wPjxwPlVuZm9y
dHVuYXRseSwgaWYgU3RyaW5nICZsdDs6IFN0cmluZ1RlbXBsYXRlLCB0aGlzIG1lYW5zIHRoYXQg
Y2FsbGluZyBmb3JtYXQgd2l0aCBhIHN0cmluZyBsaXRlcmFsIHdpbGwgcmVzb2x2ZSB0byAoMSks
IG5vdCAoMikgYXMgYmVmb3JlLiBUaGUgcHJvYmxlbSBoZXJlIGlzIHRoYXQgKDIpIGlzIG5vdCBl
dmVuIGFwcGxpY2FibGUgZHVyaW5nIHRoZSB0d28gb3ZlcmxvYWQgcmVzb2x1dGlvbiBwaGFzZXMg
KHdoaWNoIGlzIG9ubHkgYWxsb3dlZCB0byB1c2Ugc3VidHlwaW5nIGFuZCBjb252ZXJzaW9ucywg
cmVzcGVjdGl2ZWx5KSwgYXMgaXQgaXMgYSB2YXJhcmdzIG1ldGhvZC4gQmVjYXVzZSBvZiB0aGlz
LCAoMSkgd2lsbCBub3cgdGFrZSB0aGUgcHJlY2VkZW5jZSwgYXMgdGhhdCdzIG5vdCB2YXJhcmdz
LiBXaGlsZSBmb3IgU3RyaW5nOjpmb3JtYXQgdGhpcyBpcyBwcm9iYWJseSBoYXJtbGVzcywgY2hh
bmdpbmcgcmVzdWx0cyBvZiBvdmVybG9hZCBzZWxlY3Rpb24gaXMgc29tZXRoaW5nIHRoYXQgc2hv
dWxkIGJlIGRvbmUgd2l0aCBjYXJlIChlc3AuIGlmIGRpZmZlcmVudCBvdmVybG9hZHMgaGF2ZSBk
aWZmZXJlbnQgcmV0dXJuIHR5cGVzKSwgYXMgaXQgY291bGQgbGVhZCB0byBzb3VyY2UgY29tcGF0
aWJpbGl0eSBpc3N1ZXMuPC9wPjxwPk9uIHRvcCBvZiB0aGVzZSBpc3N1ZXMsIG1ha2luZyBhbGwg
c3RyaW5ncyBiZSBzdHJpbmcgdGVtcGxhdGVzIGhhcyB0aGUgZGlzYWR2YW50YWdlIG9mIGFsc28g
Y29uc2lkZXJpbmcgIm1lc3N5IiBzdHJpbmdzIG9idGFpbmVkIHZpYSBjb25jYXRlbmF0aW9uIG9m
IG5vbi1jb25zdGFudCB2YWx1ZXMgc3RyaW5nIHRlbXBsYXRlcyB0b28sIHdoaWNoIHNlZW1zIGJh
ZC48L3A+PHA+PGJyPjwvcD48cD5UbyBvdmVyY29tZSB0aGVzZSBpc3N1ZXMsIHdlIGF0dGVtcGV0
ZCB0byBhZGQgYW4gaW1wbGljaXQgY29udmVyc2lvbiBmcm9tIF9jb25zdGFudF8gc3RyaW5ncyB0
byBTdHJpbmdUZW1wbGF0ZS4gQXMgaXQgd2FzIG9ic2VydmVkIGJ5IEd1eSwgaW4gY2FzZSBvZiBh
bWJpZ3VpdGllcywgdGhlIG5vbi1jb252ZXJ0aW5nIHZhcmlhbnRzIChlLmcuIG0oU3RyaW5nKSkg
d291bGQgYmUgcHJlZmVycmVkLiBUaGF0IHNhaWQsIGluIHRoZSBhYm92ZSBleGFtcGxlICh3aXRo
IHZhcmFyZ3MpIHdlIHdvdWxkIHN0aWxsIGdldCBhIHBvdGVudGlhbGx5IGluY29tcGF0aWJsZSBj
aGFuZ2UgLSBhcyBhIHN0cmluZyBsaXRlcmFsIHdvdWxkIGJlIGFwcGxpY2FibGUgaW4gKDEpIGJl
Zm9yZSAoMikgaXMgZXZlbiBjb25zaWRlcmVkLCBzbyB0aGUgc2FtZSBjb25jZXJucyBzdXJyb3Vu
ZGluZyBvdmVybG9hZCByZXNvbHV0aW9uIGNoYW5nZXMgd291bGQgcmVtYWluLjwvcD48cD5Bbm90
aGVyIHRoaW5nIHRoYXQgY2FtZSB1cCBpcyB0aGF0IGNvbnZlcnNpb25zIGF1dG9tYXRpY2FsbHkg
YnJpbmcgaW4gY2FzdGluZyBjb252ZXJzaW9ucy4gRS5nLiBpZiB5b3UgY2FuIGdvIGZyb20gQSB0
byBCIHVzaW5nIGFzc2lnbm1lbnQgY29udmVyc2lvbiwgeW91IGNhbiB0eXBpY2FsbHkgZ28gdGhl
IHNhbWUgZGlyZWN0aW9uIHVzaW5nIGNhc3RpbmcgY29udmVyc2lvbi4gVGhpcyByYWlzZXMgdHdv
IGlzc3Vlcy4gVGhlIGZpcnN0IGlzIHRoYXQgY2FzdGluZyBjb252ZXJzaW9uIGlzIGdlbmVyYWxs
eSBhIHN5bW1ldHJpYyB0eXBlIHJlbGF0aW9uc2hpcCAoZS5nLiBpZiB5b3UgY2FuIGNhc3QgZnJv
bSBBIHRvIEIsIHRoZW4geW91IGNhbiBjYXN0IGZyb20gQiB0byBBKSwgd2hpbGUgaGVyZSB3ZSdy
ZSBtb3N0bHkgZGlzY3Vzc2luZyBhYm91dCBvbmUgZGlyZWN0aW9uLiBCdXQgdGhpcyBpcywgcGVy
aGFwcywgbm90IGEgYmlnIGRlYWwgLSBhZnRlciBhbGwsICJjb25zdGFudCBzdHJpbmdzIiBkb24n
dCBoYXZlIGEgZGVub3RhYmxlIHR5cGUsIHNvIHBlcmhhcHMgaXQgc2hvdWxkIGNvbWUgdG8gbm8g
c3VycHJpc2UgdGhhdCB5b3UgY2FuJ3QgdXNlIHRoZW0gYXMgYSBfdGFyZ2V0XyB0eXBlIGZvciBh
IGNhc3QuPC9wPjxwPlRoZSBzZWNvbmQgImlzc3VlIiBpcyB0aGF0IGNhc3RpbmcgY29udmVyc2lv
biBicmluZ3MgYWJvdXQgcGF0dGVybnMsIGFzIHRoYXQncyBob3cgcGF0dGVybiBhcHBsaWNhYmls
aXR5IGlzIGRlZmluZWQuIEZvciBpbnN0YW5jZTo8L3A+PHA+YGBgPGJyPnN3aXRjaCgiSGVsbG8i
KSB7PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyBjYXNlIFN0cmluZ1RlbXBsYXRlIHN0IC4uLjxicj59
PGJyPmBgYDxicj48YnI+VG8gbWFrZSB0aGlzIHdvcmsgd2Ugd291bGQgbmVlZCBhdCBsZWFzdCB0
byB0d2VhayBleGhhdXN0aXZlbmVzcyAob3RoZXJ3aXNlIGphdmFjIHdvdWxkIHRoaW5rIHRoZSBh
Ym92ZSBzd2l0Y2ggaXMgbm90IGV4aGF1c3RpdmUsIGFuZCBhc2sgeW91IHRvIGFkZCBhIGRlZmF1
bHQpLiBTZWNvbmRseSwgc29tZSB0d2Vha3MgdG8gdGhlIHJ1bnRpbWUgdGVzdHMgd291bGQgYmUg
cmVxdWlyZWQgYWxzby4gTm90IGltcG9zc2libGUsIGJ1dCB3b3VsZCByZXF1aXJlIHNvbWUgbW9y
ZSB3b3JrIHRvIG1ha2Ugc3VyZSB3ZSdyZSBvayB3aXRoIHRoaXMgZGlyZWN0aW9uLjwvcD48cD5B
bm90aGV0IGlzc3VlIHdpdGggdGhlIGNvbnZlcnNpb24gaXMgdGhhdCBpdCB3b3VsZCBleHBvc2Ug
YSBzaGFycCBlZGdlIGluIAp0aGUgY3VycmVudCBvdmVybG9hZCByZXNvbHV0aW9uIGFuZCBpbmZl
cmVuY2UgbWFjaGluZXJ5LiBGb3IgaW5zdGFuY2UsIAp0aGlzIHByb2dyYW0gZG9lc24ndCBjb21w
aWxlIGNvcnJlY3RseTo8YnI+Cgo8L3A+PHA+YGBgPGJyPgpMaXN0Jmx0O0ludGVnZXImZ3Q7IGxp
ID0gTGlzdC5vZigxLCAxTCk8YnI+CmBgYDwvcD4KPHA+U2ltaWxhcmx5LCB0aGlzIHByb2dyYW0g
d291bGQgYWxzbyBub3QgY29tcGlsZSBjb3JyZWN0bHk6PC9wPgo8cD5gYGA8YnI+Ckxpc3QmbHQ7
U3RyaW5nVGVtcGxhdGUmZ3Q7IGxpID0gTGlzdC5vZigiSGVsbG8iLCAiSGVsbG8gXHt3b3JsZH0i
KTs8YnI+CmBgYDwvcD4KPHA+PGJyPjwvcD48cD5UaGUgbGFzdCBwb3NzaWJpbGl0eSB3b3VsZCBi
ZSB0byBzYXkgdGhhdCBhIHN0cmluZyBsaXRlcmFsIGlzIGEgX3BvbHkgZXhwcmVzc2lvbl8uIEFz
IHN1Y2gsIGEgc3RyaW5nIGxpdGVyYWwgY2FuIGJlIHR5cGVkIHRvIGVpdGhlciBTdHJpbmcgb3Ig
U3RyaW5nVGVtcGxhdGUgZGVwZW5kaW5nIG9uIHRoZSB0YXJnZXQgdHlwZSAoZm9yIGluc3RhbmNl
LCB0aGlzIGlzIGNsb3NlIHRvIGhvdyBpbnQgbGl0ZXJhbHMgYWxzbyB3b3JrKS48L3A+PHA+VGhp
cyBhcHByb2FjaCB3b3VsZCBzdGlsbCBzdWZmZXIgZnJvbSB0aGUgc2FtZSBpbmNvbXBhdGlibGUg
b3ZlcmxvYWQgY2hhbmdlcyB3aXRoIHZhcmFyZ3MgbWV0aG9kIGFzIHRoZSBvdGhlciBhcHByb2Fj
aGVzLiBCdXQsIGF2b2lkaW5nIHRvIGFkZCBhbiBleHBsaWNpdCBjb252ZXJzaW9uLCBpdCBtYWtl
cyB0aGluZ3MgYSBsaXR0bGUgZWFzaWVyOiBmb3IgaW5zdGFuY2UsIGluIHRoZSBjYXNlIG9mIHBh
dHRlcm4gbWF0Y2hpbmcsIG5vdGhpbmcgbmVlZHMgdG8gYmUgZG9uZSwgYXMgdGhlIHN0cmluZyBs
aXRlcmFsIHdpbGwgYmUgdHVybmVkIGludG8gYSBzdHJpbmcgdGVtcGxhdGUgX2JlZm9yZV8gdGhl
IHN3aXRjaCBldmVuIHRha2VzIHBsYWNlIChtZWFuaW5nIHRoYXQgZXhpc3RpbmcgZXhoYXVzdGl2
ZW5lc3MgYW5kIHJ1bnRpbWUgY2hlY2tzIHdvdWxkIHN0aWxsIHdvcmspLiBCdXQsIHRoZXJlJ3Mg
c3RpbGwgZHJhZ29ucyBhbmQgaXJyZWd1bGFyaXRpZXMgd2hlbiBpdCBjb21lcyB0byBpbmZlcmVu
Y2UgLSBmb3IgaW5zdGFuY2U6PC9wPjxwPmBgYDxicj5MaXN0Jmx0O1N0cmluZ1RlbXBsYXRlJmd0
OyBsc3QgPSBMaXN0Lm9mKCJoZWxsbyIsICJ3b3JsZCIpOzxicj5gYGA8L3A+PHA+VGhpcyB3b3Vs
ZCBub3QgdHlwZS1jaGVjazogd2UgbmVlZCBhIHRhcmdldC10eXBlIHRvIGtub3cgd2hpY2ggd2F5
IHRoZSBsaXRlcmFsIGlzIGdvaW5nIChMaXN0OjpvZiBqdXN0IGFjY2VwdHMgYSB0eXBlLXZhcmlh
YmxlIFgpLiBOb3RlIHRoYXQgb3ZlcmxvYWQgcmVzb2x1dGlvbiBoYXBwZW5zIGF0IGEgdGltZSB3
aGVyZSB0aGUgdGFyZ2V0LXR5cGUgaXMgbm90IGtub3duLCBzbyBoZXJlIHdlJ2QgcHJvYmFibHkg
cGljayBYID0gU3RyaW5nLCB3aGljaCB3aWxsIHRoZW4gZmFpbCB0byB0eXBlLWNoZWNrIGFnYWlu
c3QgdGhlIHRhcmdldC48L3A+PHA+QW5vdGhlciBpc3N1ZSB3aXRoIHRhcmdldC10eXBpbmcgaXMg
dGhhdCBpZiB5b3UgaGF2ZSB0d28gb3ZlcmxvYWRzOjwvcD48cD5gYGA8YnI+bShTdHJpbmcpPGJy
Pm0oU3RyaW5nVGVtcGxhdGUpPGJyPmBgYDxicj48YnI+QW5kIHlvdSBjYWxsIHRoaXMgd2l0aCBh
IHN0cmluZyBsaXRlcmFsLCB5b3UgZ2V0IGFuIGFtYmlndWl0eTogeW91IGNhbiBnbyBib3RoIHdh
eXMsIGJ1dCBTdHJpbmcgYW5kIFN0cmluZ1RlbXBsYXRlIGFyZSB1bnJlbGF0ZWQgdHlwZXMsIHNv
IHdlIGNhbid0IHBpY2sgb25lIGFzICJtb3N0IHNwZWNpZmljIi4gVGhpcyBpc3N1ZSBjb3VsZCBi
ZSBhZGRyZXNzZWQsIGluIHByaW5jaXBsZSwgYnkgYWRkaW5nIGFuIGFkLWhvYyBtb3N0IHNwZWNp
ZmljIHJ1bGUgdGhhdCwgaW4gY2FzZSBvZiBhbiBhbWJpZ3VpdHksIGFsd2F5cyBnYXZlIHByZWNl
ZGVuY2UgdG8gU3RyaW5nIG92ZXIgU3RyaW5nVGVtcGxhdGUuIFdlIGRvIGEgc2ltaWxhciB0cmlj
ayBmb3IgbGFtYmRhIGV4cHJlc3Npb25zLCB3aGVyZSBpZiB0d28gbWV0aG9kIGFjY2VwdHMgc2lt
aWxhcmx5IGxvb2tpbmcgZnVuY3Rpb25hbCBpbnRlcmZhY2UsIHdlIGdpdmUgcHJlY2VkZW5jZSB0
byB0aGUgbm9uLWJveGluZyBvbmUuPC9wPjxwPkFueXdheSwgdGhlIGdlbmVyYWwgbWVzc2FnZSBo
ZXJlIGlzIHRoYXQgaXQncyBhIGJpdCBvZiBhICJwaWNrIHlvdXIgcG9zaW9uIiBzaXR1YXRpb24u
IEFkZGluZyBhIG1vcmUgZmx1aWQgcmVsYXRpb25zaGlwIGJldHdlZW4gc3RyaW5nIGFuZCB0ZW1w
bGF0ZXMgaXMgZGVmaW5pdGl2ZWx5IHBvc3NpYmxlLCBidXQgdGhlcmUgYXJlIHJpc2tzIHRoYXQg
dGhpcyB3aWxsIGltcGFjdCBuZWdhdGl2ZWx5IG90aGVyIGFyZWFzIG9mIHRoZSBsYW5ndWFnZSwg
cmlza3MgdGhhdCB3b3VsZCBuZWVkIHRvIGJlIGFzc2Vzc2VkIHZlcnkgY2FyZWZ1bGx5LjwvcD48
cD48YnI+PC9wPjxwPkFub3RoZXIsIHNpbXBsZXIsIG9wdGlvbiB3ZSBjb25zaWRlciB3YXMgdG8g
dXNlIHNvbWUga2luZCBvZiBwcmVmaXggdG8gbWFyayBhIHN0cmluZyB0ZW1wbGF0ZSBsaXRlcmFs
IChlLmcuIG1ha2UgdGhhdCBleHBsaWNpdCwgaW5zdGVhZCBvZiByZXNvcnRpbmcgdG8gbGFuZ3Vh
Z2Ugd2l6YXJkcnkpLiBUaGF0IHdvcmtzLCBidXQgaGFzIHRoZSBkaXNhZHZhbnRhZ2Ugb2YgYnJl
YWtpbmcgdGhlIHNwZWxsIHRoYXQgdGhlcmUgaXMgb25seSAib25lIHN0cmluZyBsaXRlcmFsIiwg
d2hpY2ggaXMgc29tZXRoaW5nIHdlIGhhdmUgd29ya2VkIHF1aXRlIGhhcmQgdG8gYWNoaWV2ZS48
L3A+PHA+Q2hlZXJzPGJyPk1hdXJpemlvPGJyPjwvcD48YnI+PGRpdiBjbGFzcz0ibW96LWNpdGUt
cHJlZml4Ij5PbiAwOS8wMy8yMDI0IDIzOjUyLCBCcmlhbiBHb2V0eiB3cm90ZTo8YnI+PC9kaXY+
PGJsb2NrcXVvdGUgdHlwZT0iY2l0ZSIgY2l0ZT0ibWlkOkI2RTIwNUQxLUMwQkUtNDUwNi1BMDZD
LTdERjAzQTM5MTBDMUBvcmFjbGUuY29tIj48cHJlPknigJlsbCBsZXQgTWF1cml6aW8gZ2l2ZSB0
aGUgZGV0YWlscywgYmVjYXVzZSBJ4oCZbSBzdXJlIEkgd2lsbCBoYXZlIGZvcmdvdHRlbiBvbmUg
b3IgdHdvLgo8L3ByZT48L2Jsb2NrcXVvdGU+" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0;"></div>
</div>
</body>
</html>