<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"John Rose" <john.r.rose@oracle.com><br><b>To: </b>"Brian Goetz" <brian.goetz@oracle.com>, "Archie Cobbs" <archie.cobbs@gmail.com><br><b>Cc: </b>"Gavin Bierman" <gavin.bierman@oracle.com>, "amber-dev" <amber-dev@openjdk.org><br><b>Sent: </b>Wednesday, January 14, 2026 5:15:01 AM<br><b>Subject: </b>Re: Amber features 2026<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">On 13 Jan 2026, at 18:33, Brian Goetz wrote:</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">While I totally understand why you would want to do that, I don't see the connection between pattern assignment and extending the type system to permit denotation of quantified or existential types?  I don't see any patterns in your example, only type manipulation.</p>
<p dir="auto">What you're saying is that you'd like a conversion from Foo<?> to `\exist T .
<br>
Foo<T>`.  This is understandable, as wildcards are basically existentials already, and is just as safe as the the trick of calling an out-of-line generic method.</p>
<p dir="auto">But I just don't see the connection with pattern assignment?  It seems like what you really want is "generic variables", to go along with generic methods and classes?</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">I’ve wanted this sort of thing from time to time.  I think of the ask<br>
as "local type variables", where the type variable is local to a block<br>
(tighter control than local to method or class/interface).  But it<br>
would only be set via inference, not explicitly; in that it would<br>
be a narrower feature than type variables on methods or classes.</p>
<p dir="auto">The two other type variable occurrences (method, class) offer<br>
explicit specification as well as inference.  But there is no<br>
occasion for explicit specification of a local type.  If you<br>
have a type you want to use explicitly, you just declare the<br>
local with that type.</p>
<p dir="auto">Other kinds of variables (fields, not locals) also do not benefit<br>
from having their types inferred, for the same reason that the /var/<br>
keyword is only accepted on locals.  (Inferring a type for var on<br>
an API point is dangerously obscure, not worth the concision.)</p>
<p dir="auto">So, local type vars.  The form Archie mentions is also the one<br>
that I have wondered about, these many years.</p>
<pre style="margin-left: 15px; margin-right: 15px; padding: 5px; background-color: #F7F7F7; border-radius: 5px 5px 5px 5px; overflow-x: auto; max-width: 90vw;"><code style="margin: 0; border-radius: 3px; background-color: #F7F7F7; padding: 0px;">var x1a = foo();      // x1a has type inferred from foo()
<T1> T1 x1b = foo();  // so does x1b; now it is denotable as T1
T1 x1c;               // and now x1c has the same type too
{ x1a = x1b; x1b = x1c; x1c = x1a; } // types are the same
<K2,V2> Map<K2,V2> x2 = bar();  // capturing g-type structure
<T3> T3 x3a = baz();
List<T3> x3b = bat();  // checks result of baz is list of what x3a is
<T4> T4 x4;  // ERROR; must have an initializer to drive inference
</code></pre>
<p dir="auto">This might allow some new types to become denotable, so maybe<br>
it’s dangerous.  Maybe there is some useful sanitization move<br>
that could apply to type variables captured this way, as with var.<br>
But var definitely can capture non-denotables, despite sanitization.</p>
<pre style="margin-left: 15px; margin-right: 15px; padding: 5px; background-color: #F7F7F7; border-radius: 5px 5px 5px 5px; overflow-x: auto; max-width: 90vw;"><code style="margin: 0; border-radius: 3px; background-color: #F7F7F7; padding: 0px;">var o1 = new Object() { int f; };
o1.f++;  // field WHOOZIT.f
<T2> o2a = new Object() { long f; static int Q; };
T2 o2b = o2a;  // rather odd
o2a.Q++;  // static variable reference (deprecated syntax)
o2b.Q++;  // again?
T2.Q++;   // ERROR; unless T2 is a type alias instead of a type var
</code></pre>
<p dir="auto">Oddly, the range of variation of such a type var is very narrow,<br>
since it can be driven only from one use site, the initialization.<br>
But it’s still a type var, if you squint, since the thing coming<br>
out of the initializer expression can have type vars mixed into it.</p>
<p dir="auto">Feature priority?  Very low!  It’s a "filling in the corners" move.<br>
No known important use cases.  The use case I had was avoiding<br>
refactoring to a private generic method, because the body wanted<br>
to access some local vars in an enclosing scope.  In the end,<br>
I think I just boxed the local vars in an array and moved on<br>
with the generic helper method.  It did make the code more<br>
obscure, so having a local type var would have been an aid<br>
in readability.  But it’s rare to want to name that type,<br>
and I can’t recall why I needed to.</p>
<p dir="auto">In other words, I am not asking for a JEP or RFE for this.<br>
Just laying out the case FTR, in case a use comes up later.</p>
<p dir="auto">Maybe the balance shifts if/when we get reified generics,<br>
since then there will be "more to capture".</p>
<p dir="auto">There, got it all off my chest.  Thanks Archie for fellow-traveling.<br>
Now, back to 2026.</p></div></div></blockquote><div><br></div><div>For fields, i think I would prefer to have a way to denote the type of null and bottom/nothing.</div><div><br data-mce-bogus="1"></div><div>class A {</div><div>  <T> List<T> list = List.of();</div><div>  // can be</div><div>  List<Nothing> list = List.of();</div><div>}</div><div><br data-mce-bogus="1"></div><div>Inside a method, you sometime need to access a static field (e.g. you can use it as a JIT "anchor")</div><div><br data-mce-bogus="1"></div><div>void main() {</div><div>  var o1 = new Object() { int f; static int Q; };</div><div>  o1.Q++;<br><br></div><div>  // can be</div><div>  record T1() { static int Q; }  // the compiler adds a package private constructor</div><div>  T1.Q++;</div><div><br data-mce-bogus="1"></div><div>  // or</div><div>  enum T2 { static int Q; } // the compiler adds values()/valueOf()</div><div>  T2.Q++;</div><div><br data-mce-bogus="1"></div><div>  // this does not compile</div><div>  // the keyword "final" is allowed but "static" is not</div><div>  static final class T3 { private T3() {} static int Q; }</div><div>}</div><div><br data-mce-bogus="1"></div><div>another example is the class initializer idiom</div><div><br data-mce-bogus="1"></div><div>class DBFacade {</div><div>  public static DB getLazyDB() {<br>    final class DBInit { private DBInit() {} private static final DB INSTANCE = new DB(); }</div><div>    return DBInit.INSTANCE;<br>  }</div><div>}</div><div><br data-mce-bogus="1"></div><div>Here the class DBInit is "static" because it is defined in a static context (inside the static method).</div><div><br data-mce-bogus="1"></div><div>So the two missing pieces are</div><div>- being able to denote the type of null and/or nothing,</div><div>- being able to declare a local class static *</div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">— John</p></div></div></blockquote><div><br></div><div>Rémi</div><div><br data-mce-bogus="1"></div><div>* also allow private classes in interface which is another hole to plug.</div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">

</div></div><br></blockquote></div></div></body></html>