Skip to content
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

Fix broken collection assignability check #36197

Merged
merged 1 commit into from
Sep 28, 2023
Merged

Conversation

geoand
Copy link
Contributor

@geoand geoand commented Sep 28, 2023

The check that was being done is broken
in Java 21 as that version bring SequencedCollection which List now implements

Closes: #36170

Copy link
Member

@FroMage FroMage left a comment

Choose a reason for hiding this comment

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

This works, for sure, but I find the algo a bit confusing, and the parameter names really should be changed.

private static Set<DotName> findSupertypes(DotName name, IndexView index) {
Set<DotName> result = new HashSet<>();

Deque<DotName> workQueue = new ArrayDeque<>();
Copy link
Member

Choose a reason for hiding this comment

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

I have to admit I've never seen this sort of implementation. Usually it's a recursive function. I assume you're flattening it on purpose to save stack space?
Also, this is not efficient because you will iterate through the work queue's inheritance entirely to look for all supertypes instead of stopping as soon as you find it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I pretty much copied this from Arc

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can of course optimize, but I didn't want to in the remote case we can at some point merge the various util classes

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I figured this came from somewhere :( I also wondered why it was not using the existing JandexUtil from quarkus-core-deployment, but this is not usable from independent-projects, same as for Arc. Interestingly, that last util class has isSubclassOf but not for interfaces, which means it must already exist in many forms elsewhere.

@mkouba any reason why Arc's isAssignableFrom uses findSupertypes instead of stopping on success?

Copy link
Contributor

@Ladicek Ladicek Sep 29, 2023

Choose a reason for hiding this comment

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

I rewrote this in ArC actually, so I can comment on this. The important thing that ArC does and this utility class does not is memoization. In ArC, we remember the full set of supertypes for each class, which allows us to later answer the "is subtype of" queries instantly -- we do the traversal just once.

Copy link
Contributor

Choose a reason for hiding this comment

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

See io.quarkus.arc.processor.AssignabilityCheck.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, the work queue algorithm is very common in compilers, I just mangled the name a long time ago and it kinda stuck. In compilers, it is commonly known as "worklist".

@FroMage
Copy link
Member

FroMage commented Sep 28, 2023

Very interesting bug, for sure!

The check that was being done is broken
in Java 21 as that version bring SequencedCollection
which List now implements

Closes: quarkusio#36170
@geoand geoand dismissed FroMage’s stale review September 28, 2023 14:20

Let's leave the algo discussion for when we try to merge things with Arc

Copy link
Member

@FroMage FroMage left a comment

Choose a reason for hiding this comment

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

Let's not block merging this for an optimisation, but I wonder how much is the accumulated cost of this sort of issue. Probably we're not noticing these because we don't analyse build times as much as startup times?

private static Set<DotName> findSupertypes(DotName name, IndexView index) {
Set<DotName> result = new HashSet<>();

Deque<DotName> workQueue = new ArrayDeque<>();
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I figured this came from somewhere :( I also wondered why it was not using the existing JandexUtil from quarkus-core-deployment, but this is not usable from independent-projects, same as for Arc. Interestingly, that last util class has isSubclassOf but not for interfaces, which means it must already exist in many forms elsewhere.

@mkouba any reason why Arc's isAssignableFrom uses findSupertypes instead of stopping on success?

@geoand
Copy link
Contributor Author

geoand commented Sep 28, 2023

One solution I can think of is to have a smallrye jandex util library that all projects can use

cc @Ladicek

@quarkus-bot
Copy link

quarkus-bot bot commented Sep 28, 2023

Failing Jobs - Building ffa805a

Status Name Step Failures Logs Raw logs Build scan
✔️ JVM Tests - JDK 11
✔️ JVM Tests - JDK 17
JVM Tests - JDK 20 Build Failures Logs Raw logs

Full information is available in the Build summary check run.

Failures

⚙️ JVM Tests - JDK 20 #

- Failing: extensions/hibernate-orm/deployment 
! Skipped: extensions/flyway/deployment extensions/hibernate-envers/deployment extensions/hibernate-reactive/deployment and 87 more

📦 extensions/hibernate-orm/deployment

io.quarkus.hibernate.orm.xml.persistence.ExcludePersistenceXmlConfigUsingSystemPropertyTest. - More details - Source on GitHub

java.lang.RuntimeException: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:705)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

@geoand geoand merged commit 29c2ce1 into quarkusio:main Sep 28, 2023
43 of 44 checks passed
@quarkus-bot quarkus-bot bot added this to the 3.5 - main milestone Sep 28, 2023
@geoand geoand deleted the #36170 branch September 29, 2023 08:17
@Ladicek
Copy link
Contributor

Ladicek commented Sep 29, 2023

I did think about providing a "type system" library in Jandex, but it's hard. Most of the time, we don't need the full JLS subtyping rules -- like here (and in ArC), that would be just overkill. And there are other rules than just JLS in some contexts (e.g. CDI has its own assignability rules that are in certain aspects quite different from JLS). So I never really got to doing it. The AssignabilityCheck class in ArC is pretty decent and could be just copied here, but it's important to just have a single instance to actually leverage the memoized computations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RestEasyReactive Client no longer maps List items in query param as multivalued query field in JDK21
6 participants