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

Add SIP compliant by-name implicits #5461

Merged
merged 5 commits into from
Dec 4, 2018

Conversation

milessabin
Copy link
Contributor

  • Replaced existing implementation of by-name implicits with a SIP compliant one.
  • Ported the Scala 2 tests.
  • Removed now redundant -Xmin-implicit-search-depth.

Copy link
Member

@dottybot dottybot left a comment

Choose a reason for hiding this comment

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

Hello, and thank you for opening this PR! 🎉

All contributors have signed the CLA, thank you! ❤️

Have an awesome day! ☀️

Copy link
Member

@smarter smarter left a comment

Choose a reason for hiding this comment

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

I would appreciate documentation for all the added methods and classes.

compiler/src/dotty/tools/dotc/core/Types.scala Outdated Show resolved Hide resolved
@smarter
Copy link
Member

smarter commented Nov 18, 2018

Some description in the commit of how the new semantics differs from what was implemented before would also be nice

implicitly[C[C[C[C[C[C[String]]]]]]]
Copy link
Member

Choose a reason for hiding this comment

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

How come this does not diverge anymore ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't diverge because the reduction steps are either neutral or reduce the size of the type being resolved. The description of the algorithm in the SIP explains in more detail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason it diverged previously is because the only check on divergence was a hard limit (via a command line argument) on the number of reduction steps permitted.

Copy link
Member

Choose a reason for hiding this comment

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

I see, can you also add a neg test where an implicit search diverges now ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All the neg tests in this PR report divergence.

@odersky
Copy link
Contributor

odersky commented Nov 19, 2018

test performance please

@dottybot
Copy link
Member

performance test scheduled: 1 job(s) in queue, 1 running.

compiler/src/dotty/tools/dotc/typer/Implicits.scala Outdated Show resolved Hide resolved
compiler/src/dotty/tools/dotc/typer/Implicits.scala Outdated Show resolved Hide resolved
@milessabin
Copy link
Contributor Author

Agreed that there needs to be more documentation in the PR. That said, the algorithm is described in detail in the SIP, complete with a termination proof.

@dottybot
Copy link
Member

Performance test finished successfully:

Visit http://dotty-bench.epfl.ch/5461/ to see the changes.

Benchmarks is based on merging with master (0a1aed2)

@milessabin
Copy link
Contributor Author

Rebased, added documentation and addressed feedback.

@milessabin milessabin dismissed odersky’s stale review November 26, 2018 15:39

Documentation added and addressed your and @smarter's comments.

* search history (`root`) which in turn maintains a possibly empty dictionary of
* recursive implicit terms constructed during this search.
*
* A search history provides operations to created a nested search history, check for
Copy link
Contributor

Choose a reason for hiding this comment

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

create

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

// as we ascend the chain of open implicits to the outermost search context.

@tailrec
def loop(ois: List[(Candidate, Type)], belowByname: Boolean): Boolean = {
Copy link
Contributor

Choose a reason for hiding this comment

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

redundant pair of braces? We usually put the match directly after the =.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

ois match {
case Nil => false
case (hd@(cand1, tp)) :: tl =>
(if (cand1.ref == cand.ref) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not fuse the scrutinee and the match? I.e.

if (cand1.ref == cand.ref) {
  val wideTp = tp.widenExpr
  lazy val wildTp = wildApprox(wideTp)
  if (belowByname && (wildTp <:< wildPt)) false
  else if ((wideTp.typeSize < ptSize && wideTp.coveringSet == ptCoveringSet) || (wildTp == wildPt)) true
  else loop(tl, isByname(tp) || belowByname)
}
else loop(tl, isByname(tp) || belowByname)

The recursive call is duplicated, but everything else is shorter and nicer (and less boxing, too).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed.

else {
result match {
case failure: SearchFailure => failure
case success@SearchSuccess(tree, _, _) =>
Copy link
Contributor

Choose a reason for hiding this comment

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

spaces around @

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

tpd.ref(vsymMap(id.symbol))
case tree => tree
})
val nrhss = rhss.map(rhs => rhsMap(rhs))
Copy link
Contributor

Choose a reason for hiding this comment

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

rhss.map(rhsMap(_)) maybe?

@odersky
Copy link
Contributor

odersky commented Dec 3, 2018

Looks generally good to me.

* Replaced existing implementation of by-name implicits with a SIP
  compliant one.
* Ported the Scala 2 tests.
* Removed now redundant -Xmin-implicit-search-depth.
* Fixed whitespace and comment typos.
* Simplified loop logic in checkDivergence.
@milessabin
Copy link
Contributor Author

Incorporated review feedback and rebased. I'll merge when it goes green.

@milessabin milessabin merged commit ce62b37 into scala:master Dec 4, 2018
@biboudis biboudis added this to the 0.12 Tech Preview milestone Jan 18, 2019
julienrf added a commit to scalacenter/docs.scala-lang that referenced this pull request May 3, 2022
Assigned number 36 to SIP “By-name implicit arguments”.

Implemented in Scala 2.13 in scala/scala#6050
Implemented in Scala 3 in scala/scala3#5461
julienrf added a commit to scala/improvement-proposals that referenced this pull request Jun 9, 2022
Assigned number 36 to SIP “By-name implicit arguments”.

Implemented in Scala 2.13 in scala/scala#6050
Implemented in Scala 3 in scala/scala3#5461
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.

5 participants