Overloading of matcher method Was: Deconstruction patterns
Brian Goetz
brian.goetz at oracle.com
Tue Mar 7 14:20:25 UTC 2023
>> For a deconstructor (and declared patterns in general), we derive a _binding
>> signature_ (and an erased _binding descriptor_) which treats the binding
>> list as
>> a parameter list. The overload rule outlined above requires that binding
>> signatures for two deconstructors of the same arity not be
>> override-equivalent.
>> (We will find it useful later to derive a `MethodType` for the binding
>> descriptor; this is a `MethodType` whose return type is `V` and whose
>> parameter
>> types are the erased types of the bindings.)
>
> I am still not able to compute how it is supposed to work.
> Given that inside a record pattern you can have type patterns, the type of bindings can not be used to select matcher methods, because the type of the bindings may be a subtypes of the type of the matcher method.
>
> class Foo {
> public Foo(String s) { ... }
> public Foo(CharSequence seq) { ... }
>
> public matcher Foo(String s) { ... }
> public matcher Foo(CharSequence seq) { ... }
> }
>
> If i want to call Foo(CharSequence) with a String, i can use a cast, new Foo((CharSequence) "foo") and the compiler selects the right overload.
>
> How i can do the same to select the right matcher method inside a deconstructor pattern ?
Let's start without overloads. Suppose I have
record Foo(String s) { }
and a client does
anObject instanceof Foo(String s)
This is a nested pattern; a record pattern Foo(...) with a type pattern
`String s` nested in it. The first question the compiler asks is: is
the pattern `Foo(String s)` applicable to Object? And answering this
question has two parts:
- Is the type of the record pattern (Foo) cast-convertible to Object
without unchecked conversion? (Yes)
- The first component type of Foo is String. Is the nested pattern
`String s` applicable to String? (Yes)
So since both of these are yes, `Foo(String s)` is applicable to Object.
Now imagine I have overloaded matchers:
matcher Foo(String s)
matcher Foo(Integer i)
matcher Foo(CharSequence c)
and the same use site. First, we filter for applicable matchers. The
first and third are applicable (same logic as above), the second is not
(`String s` is not applicable to Integer, because they are not
cast-convertible.)
Now, as with overloads of methods, we have to pick a "more specific".
Is matcher Foo(String s) or matcher Foo(CharSequence c) more specific
given `Foo(String s)` at the use site? The term "more specific" is a
little confusing, so a better way to think about this is minimizing the
gap between what is at the declaration site and use site. And
`Foo(String s)` is a closer match here, so we prefer that one. (The
details will be formalized, but they are pretty similar to 15.12.2.5,
minus all the goop about lambdas.)
More information about the amber-spec-observers
mailing list