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

Regression in frawa/typed-json for typer / implicit search #21249

Closed
WojciechMazur opened this issue Jul 23, 2024 · 4 comments
Closed

Regression in frawa/typed-json for typer / implicit search #21249

WojciechMazur opened this issue Jul 23, 2024 · 4 comments
Assignees
Labels
area:implicits related to implicits area:typer itype:bug regression This worked in a previous version but doesn't anymore stat:needs spec

Comments

@WojciechMazur
Copy link
Contributor

WojciechMazur commented Jul 23, 2024

Based on OpenCB failure in frawa/typed-json - https://github.com/VirtusLab/community-build3/actions/runs/10043516433/job/27756747215

Not exactly sure if it should be fixed. The compiler is now more precise which might be an improvement. I'm not sure how to workaround it though without explicitly hinting the type

Compiler version

Since 3.4.1
Last good release: 3.4.1-RC1-bin-20240126-1716bcd-NIGHTLY
First bad release: 3.4.1-RC1-bin-20240129-b20747d-NIGHTLY

Probable cause: #19096

Minimized code

sealed trait Keyword
sealed trait AssertionKeyword extends Keyword
sealed trait TypeKeyword extends AssertionKeyword
case object NullTypeKeyword extends TypeKeyword

case class Keywords(keywords: Set[Keywords.KeywordWithLocation])
object Keywords:
  type KeywordWithLocation = WithLocation[Keyword]

case class WithLocation[+T](uri: String, value: T)

trait Compare[A, B]
object Compare extends ComparePriority2:
  given compareSubtypeWithSupertype[A, B](using A <:< B): Compare[A, B] = ???
trait ComparePriority2:
  given compareSupertypeWithSubtype[A, B](using A <:< B): Compare[B, A] = ???

class KeywordsTest:
  private def assertKeywords(f: Keywords => Unit): Either[Nothing, Unit] = ???
  def assertEquals[A, B](obtained: A, expected: B)(using Compare[A, B]) = ???
  val keywords: Keywords = ???
  assertEquals(keywords.keywords, Set(WithLocation("", NullTypeKeyword))) // error
  // Summon resolves to: 
  // - in 3.4.1 Compare.compareSubtypeWithSupertype[Set[Keywords.KeywordWithLocation], Set[WithLocation[Keyword]]]
  // - in 3.4.2 Compare.compareSubtypeWithSupertype[Set[Keywords.KeywordWithLocation], Set[WithLocation[NullTypeKeyword.type]]]

Output

-- [E172] Type Error: /Users/wmazur/projects/sandbox/src/main/scala/test.scala:22:73 
22 |  assertEquals(keywords.keywords, Set(WithLocation("", NullTypeKeyword))) // error
   |                                                                         ^
   |No given instance of type Compare[Set[Keywords.KeywordWithLocation],
   |  Set[WithLocation[NullTypeKeyword.type]]] was found for parameter x$3 of method assertEquals in class KeywordsTest.
   |I found:
   |
   |    Compare.compareSubtypeWithSupertype[Set[Keywords.KeywordWithLocation],
   |      Set[WithLocation[NullTypeKeyword.type]]](
   |      /* missing */
   |        summon[Set[Keywords.KeywordWithLocation] <:<
   |          Set[WithLocation[NullTypeKeyword.type]]]
   |    )
   |
   |But no implicit values were found that match type Set[Keywords.KeywordWithLocation] <:< Set[WithLocation[NullTypeKeyword.type]].

Expectation

Not sure, but maybe it should still compile.

@Gedochao Gedochao added the regression This worked in a previous version but doesn't anymore label Jul 24, 2024
@Gedochao Gedochao assigned mbovel and unassigned EugeneFlesselle Sep 3, 2024
@mbovel
Copy link
Member

mbovel commented Oct 3, 2024

I saw a similar problem in scalameta/munit#819.

This sounds expected if we instantiate type parameters before implicit search. So I guess the solution is to add type ascriptions manually.

@mbovel
Copy link
Member

mbovel commented Oct 4, 2024

Further minimized:

// eq.scala
class C
class D extends C

class Compare[A, B]
given [A, B](using A <:< B): Compare[A, B] = Compare()

def assertEquals[A, B](obtained: A, expected: B)(using Compare[A, B]) = ???

@main def main = assertEquals(Set(C()), Set(D()))
➜  ~/scala-snippets-6 scala compile -S 3.4.1-RC1-bin-20240126-1716bcd-NIGHTLY eq.scala
Downloading Scala 3.4.1-RC1-bin-20240126-1716bcd-NIGHTLY compiler
Downloading Scala 3.4.1-RC1-bin-20240126-1716bcd-NIGHTLY bridge
Compiling project (Scala 3.4.1-RC1-bin-20240126-1716bcd-NIGHTLY, JVM (17))
Compiled project (Scala 3.4.1-RC1-bin-20240126-1716bcd-NIGHTLY, JVM (17))
➜  ~/scala-snippets-6 scala compile -S 3.4.1-RC1-bin-20240129-b20747d-NIGHTLY eq.scala
Downloading Scala 3.4.1-RC1-bin-20240129-b20747d-NIGHTLY compiler
Downloading Scala 3.4.1-RC1-bin-20240129-b20747d-NIGHTLY bridge
Compiling project (Scala 3.4.1-RC1-bin-20240129-b20747d-NIGHTLY, JVM (17))
[error] ./eq.scala:9:50
[error] No given instance of type Compare[Set[C], Set[D]] was found for parameter x$3 of method assertEquals.
[error] I found:
[error] 
[error]     given_Compare_A_B[Set[C], Set[D]](/* missing */summon[Set[C] <:< Set[D]])
[error] 
[error] But no implicit values were found that match type Set[C] <:< Set[D].
[error] @main def main = assertEquals(Set(C()), Set(D()))
[error]                                                  ^
Error compiling project (Scala 3.4.1-RC1-bin-20240129-b20747d-NIGHTLY, JVM (17))
Compilation failed

@mbovel
Copy link
Member

mbovel commented Oct 4, 2024

This sounds expected if we instantiate type parameters before implicit search. So I guess the solution is to add type ascriptions manually.

We discussed it during today's compiler meeting. I confirm the new behavior is expected.

One possible workaround is to add a type ascription to the second set (or to its element):

class C
class D extends C

class Compare[A, B]
given [A, B](using A <:< B): Compare[A, B] = Compare()

def assertEquals[A, B](obtained: A, expected: B)(using Compare[A, B]) = ???

@main def main = assertEquals(Set(C()), Set(D()): Set[C])
@main def main2 = assertEquals(Set(C()), Set(D(): C))

Another workaround is to define a specific Compare instances for Sets :

class C
class D extends C

class Compare[A, B]
object Compare extends ComparePriority2:
  given compare_sup[A, B](using A <:< B): Compare[A, B] = Compare()
  given compare_sets[A, B](using Compare[A, B]): Compare[Set[A], Set[B]] = Compare()
trait ComparePriority2:
  given compare_sub[A, B](using B <:< A): Compare[A, B] = Compare()

def assertEquals[A, B](obtained: A, expected: B)(using Compare[A, B]) = ???

@main def main = assertEquals(Set(C()), Set(D()))

@mbovel mbovel closed this as completed Oct 4, 2024
@Gedochao Gedochao closed this as not planned Won't fix, can't repro, duplicate, stale Oct 4, 2024
@WojciechMazur
Copy link
Contributor Author

@frawa This might require changes in your codebase in the future when upgrading Scala 3 version

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:implicits related to implicits area:typer itype:bug regression This worked in a previous version but doesn't anymore stat:needs spec
Projects
None yet
Development

No branches or pull requests

4 participants