Skip to content

Fix handling of arrays in java annotation arguments #8360

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

Merged
merged 4 commits into from
Mar 22, 2020

Conversation

smarter
Copy link
Member

@smarter smarter commented Feb 22, 2020

Also turn off implicit search in applyOverloaded, see commit messages for details.

Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Community build fails, so this has to be investigated if it persists.

@odersky odersky assigned smarter and unassigned odersky Feb 29, 2020
smarter added 2 commits March 18, 2020 19:18
It's not necessary and doing an implicit search after typer does not
sound like a good idea.
Previously, the array literal argument `{ "foo", "bar" }` was typed as
an `Array["foo" | "bar"]`, which is not a subtype of the corresponding
parameter type (`Array[String]`). This lead to a crash when forcing
the annotation. This is a serious problem because in Java 9+, JFrame
contains such an annotation, therefore this affects basically any code
using Swing/AWT.

Similary an empty array `{}` was always typed as `Array[Object]` which
does not always match the parameter type, this one is trickier to fix
since the serialized annotation does not keep track of the element type
of an empty array and we don't want to force the serialization at this
point, so we use a WildcardType.
@smarter
Copy link
Member Author

smarter commented Mar 18, 2020

I've implemented an alternative, cleaner fix: storing annotation arguments as untyped trees. See latest commit.

@smarter smarter requested a review from odersky March 18, 2020 19:39
We can't properly type annotation arguments which are empty array
literals because we would need the corresponding parameter type which
would require forcing the annotation constructor early. The previous
commit worked around this by using `WildcardType` as the element type
but that's a hack. Instead, we can fix the problem by always storing
annotation arguments as untyped trees and using `applyOverloaded` to
type them when the annotation tree is forced. This requires some
refactoring to make `applyOverloaded` work both with typed and untyped
arguments (the variants are now accessible using `untpd.applyOverloaded`
and `tpd.applyOverloaded`).

(the abstract `def FunProto` in Trees that gets implemented by
forwarding in untpd/tpd sounds like a good candidate for `export`,
except we can't export a class constructor)
@smarter smarter removed their assignment Mar 18, 2020
Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM

.map(denot => TermRef(receiver.tpe, denot.symbol))
.filter(tr => typeParamCount(tr) == targs.length)
.filter { _.widen match {
case MethodTpe(_, _, x: MethodType) => !x.isImplicitMethod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why drop only implicit methods that are followed by some other method type? Should this not be done for all implicit methods?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I didn't write this code, I just moved it from tpd.scala That said, this drops methods whose result type is an implicit method, e.g. if you have def foo(x: A) and def foo(x: A)(implicit y: B), it will pick the first alternative, which seems reasonable to me.

case MethodTpe(_, _, x: MethodType) => !x.isImplicitMethod
case _ => true
}}
if (targs.isEmpty) allAlts = allAlts.filterNot(_.widen.isInstanceOf[PolyType])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line looks redundant to me. PolyTypes were already filtered out in line 1537.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a follow-up commit to remove the redundant filtering.

@odersky odersky assigned smarter and unassigned odersky Mar 22, 2020
Already taken care of by the `typeParamCount(tr) == targs.length`
filtering done above.
@smarter smarter merged commit 4581490 into scala:master Mar 22, 2020
@smarter smarter deleted the fix-array-annot branch March 22, 2020 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants