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 how implicit candidates are combined #18321

Merged
merged 2 commits into from
Aug 22, 2023

Conversation

dwijnand
Copy link
Member

@dwijnand dwijnand commented Aug 1, 2023

No description provided.

@dwijnand dwijnand linked an issue Aug 1, 2023 that may be closed by this pull request
@dwijnand dwijnand assigned dwijnand and odersky and unassigned dwijnand Aug 1, 2023
@dwijnand dwijnand requested a review from odersky August 1, 2023 13:10
@dwijnand dwijnand marked this pull request as ready for review August 1, 2023 13:11
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.

I think this is getting a bit too complex for comfort.

One alternative approach to consider is to have a smarter merge where we don't immediately designate a shadowed set, but merge outerImplicits and innerImplicits according to what is better:

  • high levels beat lower
  • at equal level, definitions beat imports and named imports beat wildcard imports

@odersky odersky assigned dwijnand and unassigned odersky Aug 7, 2023
@odersky
Copy link
Contributor

odersky commented Aug 7, 2023

Something like this:

    private def combineEligibles(ownEligible: List[Candidate], outer: ContextualImplicits): List[Candidate] =
      val outerEligible = outer.uncachedEligible(tp)
      if ownEligible.isEmpty then outerEligible
      else if outerEligible.isEmpty then ownEligible
      else
        val ownNames = mutable.Set(ownEligible.map(_.ref.implicitName)*)
        if level == outer.level then
          val keptOuters = outerEligible.filterConserve: cand =>
            if ownNames.contains(cand.ref.implicitName) then
              val keepOuter = cand.level == level && cand.bindingPrec.id > bindingPrec.id
              if keepOuter then ownNames -= cand.ref.implicitName
              keepOuter
            else false
          val keptOwn = ownEligible.filterConserve: cand =>
            ownNames.contains(cand.ref.implicitName)
          keptOwn ::: keptOuters
        else
          ownEligible ::: outerEligible.filterConserve: cand =>
            !ownNames.contains(cand.ref.implicitName)

I assume a field bindingPrec: Typer.BindingPrec in ContextualImplicits and Candidate.

Not sure what to do under 3.0-migration.

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.

LGTM now

@odersky odersky assigned dwijnand and unassigned odersky Aug 21, 2023
@dwijnand dwijnand merged commit 3783220 into scala:main Aug 22, 2023
17 checks passed
@dwijnand dwijnand deleted the fix-combine-implicits branch August 22, 2023 20:28
@Kordyjan Kordyjan added this to the 3.4.0 milestone Dec 20, 2023
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.

Regression in squeryl/squeryl, changed semantics of implicits import
3 participants