I don’t object to having something explicit in the code, but I do object to
having that be unchecked. In the original example:
<T> T unbox(Node<T> n) {
return switch (n) {
case A<T> n -> n.t;
case B n -> n.s;
};
}
we could cast `n,s` to T, but the compiler would have no reason to believe that
this is valid, so it would give us an unchecked warning. But the reality is,
we do have enough information to validate this. Now, I’m not sure if users
would be any happier about
case B n -> (T) n.s
even if they did not get an unchecked warning. Still, a cast is probably
better than new, narrowly targeted syntax here.
If we’re diffident about refining the type of T, we could consider an implicit
conversion (String can be converted to T in a context where we’ve gathered the
appropriate constraints on T), but this is more complicated, and I’m not sure
users will find it any more understandable. Refining the type is something
that will make more sense to the user (“I know T is String here!”) than complex
rules about when we can funge T and String.
On Jan 26, 2022, at 9:16 AM, [email protected]<mailto:[email protected]> wrote:
________________________________
From: "Brian Goetz" <[email protected]<mailto:[email protected]>>
To: "Remi Forax" <[email protected]<mailto:[email protected]>>
Cc: "amber-spec-experts"
<[email protected]<mailto:[email protected]>>
Sent: Wednesday, January 26, 2022 1:28:19 PM
Subject: Re: [External] : Re: Patterns and GADTs (was: Reviewing feedback on
patterns in switch)
The instanceof example is not a source backward compatible change, remember
that instanceof is not a preview feature.
I’m well aware, can you give an example where flow typing of *type variables
only* might lead to incompatibility? (I’m aware that this is a possibility,
but you’re stating it like its a fact already on the table.) For example,
where it would change overload selection (this is where flow typing for
variables falls down, among other places.)
sure,
sealed interface Node<T> { }
record A<T>(T t) implements Node<T> { }
record B(String s) implements Node<String> { }
void foo(Object o) { }
void foo(List<String> list) { }
<T> void m() {
if (node instanceof B b) {
foo(List.<T>of());
}
}
Rémi