Skip to content

Given within for-comprehension not found #12646

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

Closed
qwbarch opened this issue May 30, 2021 · 5 comments · Fixed by #15403
Closed

Given within for-comprehension not found #12646

qwbarch opened this issue May 30, 2021 · 5 comments · Fixed by #15403

Comments

@qwbarch
Copy link

qwbarch commented May 30, 2021

Compiler version

3.0.0

Minimized code

Declaring a result as given works as expected if I'm flat-mapping to another monadic value. For example:

for
   given Int <- List(0)
   x <- List(summon[Int])
yield x

Scastie: https://scastie.scala-lang.org/9nPXzZH0QEaVzz3zI4ER8g

However, if the next step in the for-comprehension is a variable, the given is not found. For example:

for
   given Int <- List(0)
   x = summon[Int]
yield x

Scastie: https://scastie.scala-lang.org/1cuJc8bcS4q59Y5ZoSQ4bw

Output

no implicit argument of type Int was found for parameter x of method summon in object Predef

Expectation

It should compile just like the first example.

@smarter
Copy link
Member

smarter commented May 30, 2021

@bishabosha is this perhaps related to #12631 ?

@bishabosha
Copy link
Member

@bishabosha is this perhaps related to #12631 ?

I don't think so - it seems that the code path that recognises given pattern as irrefutable is only checked for generator enumerators not alias enumerators

https://github.com/lampepfl/dotty/blob/d9799a8e3374cd3bee8becb39c950022fb525f41/compiler/src/dotty/tools/dotc/ast/Desugar.scala#L1590

@dwijnand
Copy link
Member

Looks like the translation happens during typer. (Couldn't tell just from comparing -Xprint outputs why things go how they go.)

@kubukoz
Copy link
Contributor

kubukoz commented Sep 3, 2021

A nasty workaround that's less unpleasant than no givens at all... adding a dummy value to flatMap on before you use the newly created given.

trait demo {
  trait A
  trait B
  def mkA: Option[A]
  def mkB(using A): B

  val dummy: Option[Any] = Some(42)

  def example = for {
    given A <- mkA
    _ <- dummy
    given B = mkB
  } yield ()
}

but yeah, it would be great if it just worked. FWIW it seems withFilter is involved, ignoring the <- dummy line with a type that doesn't have it issues:

value withFilter is not a member of demo.this.Op[demo.this.A]
code that produced this
trait demo {
  trait Op[X] {
    def flatMap[B](f: X => Op[B]): Op[B]
    def map[B](f: X => B): Op[B]
  }
  trait A
  trait B
  def mkA: Op[A]
  def mkB(using A): B

  val dummy: Op[Any]

  def example = for {
    given A <- mkA
    // _ <- dummy
    given B = mkB
  } yield ()
}

all tested on 3.0.2.

Update: still happens on 3.1.0-RC3

@bishabosha
Copy link
Member

another example from #14836

trait C
object C:
  def provide: Option[C] = Some(new C {})

def consume(arg: Int)(using C): Unit = ()

val result1 = for {
  given C <- C.provide
  a = consume(42) // Error: no implicit of type C
} yield a


val result2 = for {
  c <- C.provide
  a = {
    given C = c
    consume(42) // this works fine
  }
} yield a

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

Successfully merging a pull request may close this issue.

6 participants