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

Quill idiom for inferred implicit type with whitebox macro under -Xsource:3 #12798

Closed
jilen opened this issue Jun 5, 2023 · 24 comments · Fixed by scala/scala#10439
Closed

Quill idiom for inferred implicit type with whitebox macro under -Xsource:3 #12798

jilen opened this issue Jun 5, 2023 · 24 comments · Fixed by scala/scala#10439
Assignees
Milestone

Comments

@jilen
Copy link

jilen commented Jun 5, 2023

The scala 2.13.11 version requires explicit type of implicit definition.
Then it become impossible to use whitebox macro to return the narrowed type.

@SethTisue
Copy link
Member

SethTisue commented Jun 5, 2023

The change in question is scala/scala#10083. /cc @som-snytt

Can you give an example of what you can't do now?

@SethTisue
Copy link
Member

Can the macro emit @annotation.nowarn("cat=other-implicit-type")?

@som-snytt
Copy link

This is pre-second-coffee, but you can always write : Any and the whitebox macro produces a narrower type.

@SethTisue
Copy link
Member

@som-snytt any advice we have for macro authors would be good to add to the PR description

@som-snytt
Copy link

I added a line to the PR without thinking about it, but please add a use case here if necessary.

@jilen
Copy link
Author

jilen commented Jun 6, 2023

@SethTisue

Can you give an example of what you can't do now?

The case for me is defining quill's QueryMeta

implicit val  personMeta = materializedQueryMeta[Person]

Quill will use the concrete type info later. If specify type to QueryMeta[Person] it will become dynamic query.

@jilen jilen changed the title Cant not make implicit definition with whitebox macro under -Xsource:3 Cant not make implicit definition return narrowed type with whitebox macro under -Xsource:3 Jun 6, 2023
@som-snytt
Copy link

@jilen Does that mean implicit val personMeta: Any = materializedQueryMeta[Person] does not work? I looked briefly at quill last year in the context of a bug related to macro and result inference, but I don't remember much about it.

@jilen
Copy link
Author

jilen commented Jun 6, 2023

@som-snytt Confirmed adding : Any gets things done. Thanks

@jilen jilen closed this as completed Jun 6, 2023
@SethTisue SethTisue added this to the 2.13.11 milestone Jun 6, 2023
@jilen jilen reopened this Jun 6, 2023
@jilen
Copy link
Author

jilen commented Jun 6, 2023

My bad, just find Any not working

//> using lib org.scala-lang:scala-reflect:2.13.11
//> using scala "2.13.11"
//> using options -Xsource:3

import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros

class FooMacroImpl(val c: Context) {
  import c.universe._

  def fooImpl: Tree = {
    val c = Constant("foo")
    q"${c}"
  }
}

object Foo {
  def foo: String  = macro FooMacroImpl.fooImpl
}

Then

scala> implicit val foo: Any = Foo.foo
val foo: Any = foo

@SethTisue
Copy link
Member

@jilen what behavior did you expect, there?

@jilen
Copy link
Author

jilen commented Jun 6, 2023

@jilen what behavior did you expect, there?

implicit val foo: Any = Foo.foo

I thought the type of foo should be String (returned by whitebox macro)

@som-snytt
Copy link

I'll take a look today. I don't want anything to spoil Seth's Scala Days. Because really, how many Scala Days do have in this life? Every Scala Day is precious.

@som-snytt som-snytt self-assigned this Jun 6, 2023
@SethTisue
Copy link
Member

I thought the type of foo should be String (returned by whitebox macro)

Ah, I had misunderstood Som's suggestion, but I understand better now.

I'm surprised to learn that that would be expected behavior. when I write implicit val foo: Any = ..., I would not have expected anything I could substitute for ... to have any influence on what type foo gets, give that I explicitly asked for the type to be Any.

@som-snytt you're sure that's expected...?

I guess in Scala 3 this issue can't arise because there aren't whitebox macros...? Perhaps one possible resolution here would be to say that it's expected for -Xsource:3 to complain when you're doing something that isn't even possible in Scala 3 at all?

perhaps @guizmaii could enlighten us on how people using Scala 3 with Quill would be expected to write this code?

@som-snytt
Copy link

som-snytt commented Jun 6, 2023

@SethTisue Yes, it's fundamental to whiteboxness and also works that way in Scala 3 via transparent inline.

Oh wait, sorry lack of sleep, the implicit is in the wrong place.

implicit def myimplicit: Any = macro mywhitebox

lets the type of myimplicit expansion get refined.

I'll take a look at how the behavior is relied upon in quill.

@SethTisue
Copy link
Member

SethTisue commented Jun 6, 2023

implicit def myimplicit: Any = macro mywhitebox
lets the type of myimplicit expansion get refined.

Okay, that makes more sense.

But it doesn't seem to help OP. Their desire to have an implicit val with an inferred type is fundamentally at odds with the explicit-type requirement.

also works that way in Scala 3 via transparent inline

I'd like to see a spelled-out example of that; in Scala 3, can I have a given whose type isn't written, but comes from a transparent inline?

@SethTisue
Copy link
Member

@som-snytt One thing I don't know here is whether the @nowarn mechanism is sufficiently powerful to convert an error (at least some kind of errors, I mean) into a warning, or to silence it altogether? Or does the way scala/scala#10083 is implemented prevent that?

@som-snytt
Copy link

They call it issueNormalTypeError. So it means no soup for you. Now we also know why it's called quill, it's not the writing implement but the porcupine defense mechanism. I would have named it sharpie to make the dual metaphor explicit.

@som-snytt som-snytt changed the title Cant not make implicit definition return narrowed type with whitebox macro under -Xsource:3 Quill idiom for inferred implicit type with whitebox macro under -Xsource:3 Jun 6, 2023
@SethTisue SethTisue modified the milestones: 2.13.11, 2.13.12 Jun 6, 2023
@dwijnand
Copy link
Member

dwijnand commented Jun 6, 2023

I'd like to see a spelled-out example of that; in Scala 3, can I have a given whose type isn't written, but comes from a transparent inline?

It's written but it's also transparent: https://dotty.epfl.ch/docs/reference/contextual/givens.html#given-macros-1

@leszekgruchala
Copy link

We cannot update to 2.13.11 because of this issue and the fact we cannot add explicit types for Quill. We use -Xsource:3 and I see -Wconf:cat=other-implicit-type:s is simply being ignored with that option together.

@lrytz
Copy link
Member

lrytz commented Jun 19, 2023

Not sure if this is clear from the discussion, sorry if I'm just adding noise; the static type of an implicit whitebox macro def defines what type can be summoned:

import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
class A
class B extends A

class FooMacroImpl(val c: Context) {
  import c.universe._
  def fooImpl: Tree = {
    q"new B()"
  }
}
object Foo {
  implicit def foo: A = macro FooMacroImpl.fooImpl
}
scala> import Foo._
import Foo._

scala> foo
val res0: B = B@49005dc4

scala> implicitly[B]
                 ^
       error: could not find implicit value for parameter e: B

scala> implicitly[A]
val res2: A = B@a1e578f

@lrytz
Copy link
Member

lrytz commented Jun 19, 2023

A good approach to migration errors under -Xsource:3 could be to make them fatal warnings instead, and allow users to override that default using -Wconf / @nowarn.

@som-snytt
Copy link

som-snytt commented Jun 20, 2023

I'll pursue that approach: instead of knobs to enable migration behaviors, -Wconf provides levers for the warnings, and for behaviors such as override inference, emit warnings. The implicit search change was split out, and never received subsequent attention. The are a handful of behaviors which are not mere syntax or checks.

Note to self: one way to simplify -Xlint/-Wconf is instead of enabling lints, you silence their output. (Internally, silencing a lint category could just turn off the lint.)

@nafg
Copy link

nafg commented Sep 22, 2023

Bottom line what do I do with scala 2.13.12?

@som-snytt
Copy link

Top line, the idiom of the title is -Wconf:cat=scala3-migration:s .

Sample potential dogfooding at https://github.com/scala/scala/pull/10551/files#diff-5634c415cd8c8504fdb973a3ed092300b43c4b8fc1e184f7249eb29a55511f91R417

compile / scalacOptions ++= Seq("-Wconf:cat=scala3-migration&msg=elidable&site=scala.Predef:s"),

The wconf is :e by default to error, so :s silences it and :w dials it back to warning, etc.

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