<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4" face="monospace">I just want to point out that
there's a sort of "syntax error" in your proposal. <br>
<br>
Java provides annotations as a means of "structured comments" on
declarations and type uses, but the Java language does not, and
will not, impart any semantics to programs on the basis of
annotations. If you are talking about writing a static analysis
tool, perhaps a pluggable checker in the Checkers framework, then
(as Ethan points out) you can use existing annotations with APs
and do so, and the compiler is merely a conduit for ferrying the
annotations to where an AP can find them. (In fact, there is
already a checker for "fake enums", where you say that a given
`int` is really one of the enumerated set 1, 2, 3, 4, which is a
restriction type.)<br>
<br>
If you mean that the compiler actually is going to get into the
act, though, then this is not an annotation-driven feature, this
is a full-blown language feature and should be thought of
accordingly. I know its tempting to view annos as a "shortcut" to
language features, but if something has semantics, its part of the
language, and sadly that means no shortcuts. That's not to say it
isn't a worthwhile idea with a good cost-to-benefit ratio.
(Indeed, as we get further into the type classes work, the logic
of a `newtype` mechanism becomes even more compelling as then it
becomes possible to affect behavior with restrictions such as
`CaseInsensitveString`, which doesn't actually restrict the value
set of the type, but allows you to define `Ord
CaseInsentiveString` separate from `Ord String`.)<br>
<br>
<br>
</font><br>
<div class="moz-cite-prefix">On 10/13/2025 3:17 PM, Archie Cobbs
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CANSoFxtmH7BiMXMWKc-P81XNoxvjZKWDNf94ZGJuAEKxgenzCw@mail.gmail.com">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div>Ethan McCue <<a href="mailto:ethan@mccue.dev" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">ethan@mccue.dev</a>>
wrote:</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">However
there is nothing conceptually preventing the tools
validating @NonNull usage from also emitting an
error until you have inserted a known precheck.<br>
...<br>
But for other single-value invariants, like your
@PhoneNumber example, it seems fairly practical.
Especially since, as a general rule, arbitrary cost
computations really shouldn't be invisible. How
would one know if (@B A) is going to thread
invocations of some validation method everywhere?</blockquote>
<div><br>
</div>
<div>This is why 3rd party tools aren't as good as
having the compiler handle it, because the compiler
is in a position to provide both stronger and more
efficient guarantees - think generic types and
runtime erasure. Compiler-supported typing allows
the developer to move the burden of proof from the
method receiving a parameter to the code invoking
that method, and onward back up the call chain, so
that validations tend to occur "early", when they
are first known to be true, instead of "late" at the
(many more) points in the code where someone
actually cares that they are true.</div>
<div><br>
</div>
<div>So if phone numbers are central to your
application, and they are passed around and used all
over the place as type<span style="font-family:monospace"> @PhoneNumber String</span>,
then they will only need to actually be validated at
a few application entry points, not at the start of
every method that has a phone number as a parameter.
In other words, the annotation is ideally not a
"to-do" list but rather an "it's already done" list.</div>
<div><br>
</div>
<div>The guarantee that the compiler would then
provide is ideally on the same level as with
generics: while it's being provided by the compiler,
not the JVM, so you can always get around it if you
try hard enough (native code, reflection, class file
switcheroo, etc.), as long as you "follow the rules"
you get the guarantee - or if not, an error or at
least a warning.</div>
<br>
<div>Brian Goetz <<a href="mailto:brian.goetz@oracle.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">brian.goetz@oracle.com</a>>
wrote:</div>
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>I think the best bet for making this usable
would be some mechanism like a "view", likely
only on value types, that would erase down to
the underlying wrapped type, but interpose
yourself on construction, and provided a
conversion from T to RefinedT that verified the
requirement. But this is both nontrivial and
presumes a lot of stuff we don't even have
yet...</div>
</blockquote>
<div><br>
</div>
<div>I think that is close to what I was imagining.
It seems like it could be done with fairly minimal
impact/disruption...? No need for wrappers or
views.</div>
<div><br>
</div>
<div>But first just to be clear, what I'm getting at
here is a fairly narrow idea, i.e., what
relatively simple thing might the compiler do,
with a worthwhile cost/benefit ratio, to make it
easier for developers to reason about the
correctness of their code when "type restriction"
is being used, either formally or informally
(meaning, if you're using an int to pass around
the size of collection, you're doing informal type
restriction).</div>
<div><br>
</div>
<div>What's the benefit? Type restriction is fairly
pervasive, and yet because Java doesn't make it
very easy to do, it's often not being done at all,
and this ends up adding to the amount of manual
work developers must do to prove to themselves
their code is correct. The more of this burden the
compiler could take on, the bigger the benefit
would be.</div>
<div><br>
</div>
<div>What's the cost? That depends on the solution
of course.</div>
<br>
</div>
<div class="gmail_quote">To me the giant poster-child
for this kind of pragmatic language addition is
generics. It had all kinds of minor flaws from the
point of view of language design, but the problem it
addressed was so pervasive, and the new tool it
provided to developers for verifying the correctness
of their code was so powerful, that nobody thinks it
wasn't worth the trade-off.</div>
<div class="gmail_quote"><br>
</div>
<div class="gmail_quote">OK let me throw out two
straw-man proposals. I'll just assume these are
stupid/naive ideas with major flaws. Hopefully they
can at least help map out the usable territory - if
any exists.</div>
<div class="gmail_quote">
<div>
<div><br>
</div>
<b>Proposal #1</b></div>
<div><br>
</div>
<div>This one is very simple, but provides a weaker
guarantee.</div>
<div>
<div>
<ol>
<li>The compiler recognizes and tracks "type
restriction annotations", which are type
annotations having the<span style="font-family:monospace"></span>
meta-annotation <span style="font-family:monospace">@TypeRestriction</span></li>
<li>For all operations assigning some value v
of type S to type T:</li>
<ol>
<li>If a type restriction annotation A is
present on T but not S, the compiler
generates a warning in the new lint
category <span style="font-family:monospace">"type-restriction"</span></li>
</ol>
</ol>
</div>
That's it. A cast like<span style="font-family:monospace"> var pn =
(@PhoneNumber String)input </span>functions
simply as a developer assertion that the type
restriction has been verified, but the compiler
does not actually check this. There is no change
to the generated bytecode. If the developer
chooses to write a validation method that takes a
string, validates it (or throws an exception), and
then returns the validated string, that method
will need to be annotated with<span style="font-family:monospace">
@SuppressWarnings("type-restriction") </span><span style="font-family:arial,sans-serif">because of
the cast in front of the return statement.</span>
<div><br>
</div>
<div>Guarantee provided: Proper type restriction
as long as "type-restriction" warnings are
enabled and not emitted. However, this is a
"fail slow" guarantee: it's easy to defeat (just
cast!). So if you write a method that takes a<span style="font-family:monospace"> @PhoneNumber
String </span>parameter that is passed an
invalid value, you won't find out until
something goes wrong later down the line (or
never). In other words, <i>your</i> code will
be correct, but you have to be trusting of any
code that <i>invokes</i> your code, which in
practice is not always a sound strategy.</div>
<div><br>
</div>
<div><b>Proposal #2</b></div>
</div>
<div><br>
</div>
<div>
<div>This is proposal is more complex but provides
a stronger guarantee:</div>
</div>
</div>
<div>
<ol>
<li>The compiler recognizes and tracks "type
restriction annotations", which have the<span style="font-family:monospace"></span>
meta-annotation <span style="font-family:monospace">@TypeRestriction</span></li>
<ol>
<li><span style="font-family:arial,sans-serif">The
annotation specifies a user-supplied
"constructor" class providing a user-defined
construction/validation method </span><span style="font-family:monospace">validate(v)</span></li>
<li>We add <span style="font-family:monospace">class
TypeRestrictionException extends
RuntimeException</span> and encourage <span style="font-family:monospace">validate()</span>
methods to throw (some subclass of) it</li>
</ol>
<li>For all operations assigning some value v of
type S to type T:</li>
<ol>
<li>If a type restriction annotation A is
present on T but not S, the compiler generates
a <span style="font-family:monospace">"type-restriction"</span> warning
AND adds an implicit cast added (see next
step)</li>
</ol>
<li>For every cast like <span style="font-family:monospace">var pn =
(@PhoneNumber String)"+15105551212" </span> the
compiler inserts bytecode to invoke the
appropriate enforcer<span style="font-family:monospace"> validate(v) </span>method</li>
<li><span style="font-family:arial,sans-serif">The
JLS rules for method resolution, type
inference, etc., do not change (that would be
way over-complicating things)</span></li>
<ol>
<li>Two methods<span style="font-family:monospace"> void
dial(String pn) </span>and<span style="font-family:monospace"> void
dial(@PhoneNumber String pn) </span>will
still collide</li>
</ol>
</ol>
</div>
<div>
<div>Guarantee provided: Proper type restriction
unless you are going to extremes (native code,
reflection, runtime classfile switcheroo, etc.).
This is a "fail fast" guarantee: errors are caught
at the moment an invalid value is assigned to a
type-restricted variable. If your method
parameters have the annotation, you don't have to
trust 3rd party code that calls those methods (as
long as it was compiled properly). I.e., same
level of guarantee as generics.</div>
</div>
<div><br>
</div>
<div>These are by no means complete or
particularly elegant solutions from a language
design point of view. They are pragmatic and
relatively unobtrusive add-ons, using existing
language concepts, to get us most of what we want,
which is:</div>
<div>
<ul>
<li>User-defined "custom" type restrictions with
compile-time checking/enforcement</li>
<ul>
<li>As with generics, the goal is not language
perfection, but rather making it easier for
developers to reason about correctness</li>
</ul>
<li>Compile-time guarantees that type restricted
values in source files will be actually type
restricted at runtime</li>
<li>Efficient implementation</li>
<ul>
<li>Validation only happens "when necessary"</li>
<li>No JVM changes needed (erasure)</li>
</ul>
<li>No changes to language syntax; existing source
files are 100% backward compatible</li>
</ul>
</div>
<div>
<div>The developer side of me says that the
cost/benefit ratio of something like this would be
worthwhile, in spite of its pragmatic nature,
simply because the problem being addressed seems
so pervasive. I felt the same way about generics
(which was a much bigger change addressing a
much bigger pervasive problem).</div>
<div><br>
</div>
<div>But I'm sure there are things I'm missing... ?<br>
<div><br>
</div>
<div>-Archie</div>
</div>
</div>
</div>
<div dir="ltr"><span class="gmail_signature_prefix"><br>
</span></div>
<div dir="ltr"><span class="gmail_signature_prefix">-- </span><br>
<div dir="ltr" class="gmail_signature">Archie L. Cobbs<br>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
<br>
</body>
</html>