New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@In/@Out annotations for declaration-site variance -- kind of #72
Comments
@In
/ @Out
annotations for declaration-site variance -- kind of
re: Effect no. 2: actually, we can do this anyway, for method bodies that we can observe are only calling producer methods or only consumer methods. But sometimes the method wouldn't be able to change because it overrides an abstract method. What the annotations would allow is for us to validate the abstract methods, at least in cases where the type really is variant. Still can't do much about an interface method accepting a wildcardless List. |
(for no particular reason I discussed this feature at length on a reddit post.) |
Is there a workable checker that can ensure users have In other words, since |
I agree -- in the meantime until this issue is resolved, it would be nice if the tools went ahead and caught those problems using hardcoded lists or other means. I'm surprised we never did it in Error Prone! Thanks for filing the issue there; we'll see what Liam thinks. |
It looks like one more annotation is needed: |
What advantages does this produce over not annotating at all? |
Suppose the user wants to have If they keep the type unannotated, then checkers should complain the variance is missing. |
I think that would be false information though; it would be better to see a suppression there. We can explore use-site annotations in a separate issue, assuming this one gets any traction. At declaration-site, it does seem that any type parameter not marked as In or Out should be assumed invariant. |
Are there also a series of types for which we wouldn't add variance? For example: |
How do you suggest implementing a suppression?
|
Why wouldn't it be the latter? |
Assumption is to let It's too bad that Java doesn't support finer-grained scopes for it, but solving that would be a separate problem (and there are at least 2 ways to go about it). |
These annotations would be used like:
interface Function<@In F, @Out T> {}
This represents the interface's promise that it will not use
F
as an out-type, nor useT
as an in-type (hasty definitions at bottom).Tools could presumably use this information in ways including the following:
Effect no. 1: Validating that "promise" in the type itself (including inherited members). Using
class Foo<@Out T>
as example:T
must beT
or involveT
in an "out"/covariant senseT
must involveT
in the "in"/contravariant directionT
in any way must be final.(It's a bit harder than this...)
Effect no. 2: type usages of
Foo
could be validated, enforcing proper use of wildcards as given in Effective Java. (We have no way to help users whose wish is to avoid wildcards.)Effect no. 3: screening out unchecked warnings from the compiler for the con(ntra)variant cast idiom. [EDIT: this needs explanation. Google, internally, is quite selective about which javac unchecked warnings we allow to be surfaced to users. The warning for a cast like
(Iterator<Object>) (Iterator) stringIterator
could be hidden if we had knowledge thatIterator
type is covariant.]Effect no. 4: nullness analysis could exploit this information as discussed in #40.
Effect no. 5: callers from kotlin should benefit as if the API had real DSV. (Andrey thinks feasible)
In addition: if JEP 300 lands and DSV comes to Java, this would leave us very well-positioned to migrate to it - not to mention that we would have the best possible data to support how it should be designed.
Iterable
would beIterable<@Out T>
butCollection
would drop the@Out
. Compiling a class likeCollection
in this example should produce a warning. That warning will often be suppressed, but then I think any downcast of Iterable to Collection or below should also produce a similar warning at that site as well... where it may also be suppressed but what can you do.Interestingly
ImmutableCollection
would re-add the@Out
again, and would thus need to suppress a warning on all the mutation methods.out-type = root type in a return type or final field; the type after an “extends” wildcard under an out-type; the type after a “super” wildcard under an in-type
in-type = root type of a parameter; the type after an “extends” wildcard of an in-type; the type after a “super” wildcard of an out-type
The text was updated successfully, but these errors were encountered: