Re: Type test patterns: allow expression type to match pattern type

Anthony Vanelverdinghe dev at anthonyv.be
Mon Apr 5 07:45:18 UTC 2021


Thanks for the instructive response and spot-on diagnosis, Brian. What would've helped me connect the dots myself in this case, is mentioning totality in the error message, something like "pattern type {1} is total on expression type {0}" (rather than the current "expression type {0} is a subtype of pattern type {1}"). But I assume this isn't possible for now, since the concept isn't actually defined in the JLS yet.

Kind regards, Anthony

On Sunday, April 04, 2021 22:25 CEST, Brian Goetz <brian.goetz at oracle.com> wrote: 
 
> 
> On 4/4/2021 1:16 PM, Anthony Vanelverdinghe wrote:
> > When using a type test pattern, the compiler gives an error if the expression type is a subtype of the pattern type.
> > While I agree that it doesn't make sense for the expression type to be a strict subtype, I believe it should be allowed to be the same type.
> 
> More precisely, the compiler ensures that the pattern type is 
> _applicable_ to the expression type.  For reference type patterns, 
> applicability means strict subtyping.
> 
> You're asking if we could relax this.  In theory, yes, but the choice to 
> not permit total patterns in instanceof (which is what would happen if 
> we allowed you use the exact type) was a deliberate choice, to work 
> around the legacy behavior of `instanceof`, and to prevent bugs.  And in 
> fact, the bug it prevented is exactly the bug you almost made, because 
> you were trying to use a total type pattern as a null check, which 
> wouldn't have worked the way you wanted.
> 
> For reasons that have been litigated to death, the semantics of matching 
> a type pattern `T t` to a target of type `U` are:
> 
>   - If T is total on U, then it matches all values of U, including null;
>   - If T is not total on U, then it is equivalent to `instanceof U`.
> 
> This is the natural semantics for matching patterns, but it does cause a 
> sharp edge relative the legacy meaning of `instanceof`.  It means that:
> 
>      (x instanceof Object)
> 
> and
> 
>      (x instanceof Object o)
> 
> agree everywhere -- except null.  Because these two are so syntactically 
> similar, but would not mean the same thing, we restricted the pattern on 
> the RHS of `instanceof` to patterns that _actually ask a question_.  If 
> we allowed `x instanceof Object o`, this would be equivalent to `true`, 
> which would be surprising to many developers, including you.  So this 
> sharp edge was resolved in favor of "instanceof must actually ask a 
> question".  (There are ample other places where Java doesn't let you 
> write "dumb" code, such as unreachable statements, for the same reason.)
> 
> The diagnosis here, though, is that you tried to out-clever yourself by 
> using a nullable pattern as a null check, instead of writing what you 
> really wanted to ask -- is this thing null.)
> 
> At some point, we might consider strictly non-nullable type patterns 
> (e.g., `x instanceof String! s`), but we would want to do this in the 
> context of a more comprehensive treatment of nullability.
> 
> Looking ahead, what this really illustrates, though, is that methods 
> like Map::get are the problem.  Map::get pretends to be total, but 
> really is partial.  Really, Map::get should not be a method that returns 
> a distinguished sentinel on failure, but should be a _partial pattern_ 
> on maps.  Then you'd say something like:
> 
>      if (map instanceof Map.containing(k)(var v)) { ... can use v here }
> 
> 
> 
> 
> 
> >
> > For example, with a `NavigableMap<String, String> map`, instead of writing:
> > if(map.higherKey("foo") != null) {
> >      Files.writeString(path, map.higherKey("foo"));
> > }
> >
> > We could write:
> > if(map.higherKey("foo") instanceof String kNext) {
> >      Files.writeString(path, kNext);
> > }
> >
> > Or, with a `BufferedReader in`, instead of writing:
> > String line;
> > while((line = in.readLine()) != null) { ... }
> >
> > We could write:
> > while(in.readLine() instanceof String line) { ... }
> >
> > Has this idea been considered before? If so, why was it turned down? If not, shall I file an RFE for this?
> >
> > Kind regards,
> > Anthony
> >
>



More information about the amber-dev mailing list