Skip to content

Compare types as capture sets in mergeRefinedOrApplied #23045

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

DolphinChips
Copy link

Closes #23032.

Copy link
Contributor

@bracevac bracevac left a comment

Choose a reason for hiding this comment

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

This seems good and makes sense (pending the CI)! But I fail to see the connection to "capture sets" (a term used by the experimental capture checking feature) and suggest using a more appropriate title.

@DolphinChips
Copy link
Author

This seems good and makes sense (pending the CI)! But I fail to see the connection to "capture sets" (a term used by the experimental capture checking feature) and suggest using a more appropriate title.

I used this title because I assumed that =:= comes from cc/CaptureSet.scala rather than core/Types.scala :D I'll push updated commit after CI finishes.

@@ -278,7 +278,7 @@ object TypeOps:
}
case AndType(tp11, tp12) =>
mergeRefinedOrApplied(tp11, tp2) & mergeRefinedOrApplied(tp12, tp2)
case tp1: TypeParamRef if tp1 == tp2 => tp1
Copy link
Member

Choose a reason for hiding this comment

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

=:= uses TypeComparer to check two types are equivalent (subtypes of each other), which is expensive and we need to be careful when using it.

The reason we have one TypeParamRef and one TypeVar is because we choose to widen tp1 in approximateOr.

I would like to try the following:

case tp1: TypeParamRef =>
  tp2.stripTypeVar match
    case tp2: TypeParamRef if tp1 == tp2 => tp1
    case _ => fail
case tp1: TypeVar =>
  tp2 match
    case tp2: TypeVar if tp1 == tp2 => tp1
    case tp2: TypeParamRef if tp1.stripTypeVar == tp2 => tp2
    case _ => fail

Copy link
Author

Choose a reason for hiding this comment

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

Your suggested change works. I also decided to experiment with other solutions and found out that either adding the following case:

case tp1 if tp1.stripTypeVar == tp2.stripTypeVar => tp1

or applying the following patch

-       case tp1: TypeParamRef if tp1 == tp2 => tp1
+       case tp1: TypeParamRef if tp1 == tp2.stripTypeVar => tp1

also fix the issue. So my questions are:

  1. Is it possible to hit case tp1: TypeVar branch?
  2. is adding .stripTypeVar also a valid solution?

Copy link
Member

Choose a reason for hiding this comment

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

  1. case tp1: TypeVar can be hit if tp1 is TypeVar and tp2 is TypeParamRef, although it may not happen here because the left branch of a union type is widened first in approximateOr if both sides widening succeed (see 2.6). Since the ordering is arbitary, I think it's better to cover all possibilities in case the algorithm is changed.
  2. I would match a specific type (TypeParamRef and TypeVar) before stripTypeVar, to avoid covering unintended types.

@noti0na1
Copy link
Member

Related PR: #20090

@noti0na1 noti0na1 assigned DolphinChips and unassigned noti0na1 Apr 24, 2025
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.

java.lang.AssertionError: Failure to join alternatives F and F
3 participants