Skip to content

any2stringadd inferred for anonymous given in for comprehension #10178

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
bishabosha opened this issue Nov 5, 2020 · 1 comment
Closed

any2stringadd inferred for anonymous given in for comprehension #10178

bishabosha opened this issue Nov 5, 2020 · 1 comment
Assignees

Comments

@bishabosha
Copy link
Member

Minimized code

def foo = for {                                                                                         
  x <- Option(23)
  given Int = x
} ()

Output

3 |  given Int = x
  |  ^
  |this case is unreachable since type any2stringadd$ and class Integer are unrelated

Expectation

@bishabosha
Copy link
Member Author

in the typer we can see what was inferred:

def foo: Unit = 
  Option.apply[Int](23).map[(Int, any2stringadd.type)](
    {
      def $anonfun(x: Int): (Int, any2stringadd.type) = 
        {
          x:(x : Int) @unchecked match 
            {
              case given given_Int @ _:Int => ()
            }
          Tuple2.apply[Int, any2stringadd.type](x, _)
        }
      closure($anonfun)
    }
  ).foreach[Unit](
    {
      def $anonfun(x$1: (Int, any2stringadd.type)): Unit = 
        x$1:(x$1 : (Int, any2stringadd.type)) @unchecked match 
          {
            case 
              Tuple2.unapply[Int, any2stringadd.type](x @ _, 
                given given_Int @ _:Int
              )
              => ()
          }
      closure($anonfun)
    }
  )

@bishabosha bishabosha changed the title strange error for given Int = x in for comprehension any2stringadd inferred for anonymous given in for comprehension Nov 5, 2020
@odersky odersky self-assigned this Nov 5, 2020
odersky added a commit to dotty-staging/dotty that referenced this issue Nov 5, 2020
This was a very interesting bug. Why did `any2stringadd` appear out of the blue?
The first observation was that it was resolved by an import of an identifier with
`_` as its name. Why? Because we have a standard predefined import
```scala
import Predef.{any2stringadd => _, _}
```
The correct encoding for the removal `_` is as an empty tree, but by mistake
we generated an import with a `_` ident instead. So this counted as a renaming
of `any2stringadd` to the identifier `_`.

How did we end up with an identifier `_` that needed to be resolved? This was a
second bug in Desugar, method `makeIdPat`. Here we needed to create binds for parts
of a pattern. If the pattern was already a Bind, we used that one instead. But the
`Bind` in question was anonymous, using `_` as the pattern variable. So we did not
replace that by a fresh identifier, but used `_` as the identifier instead. However,
`_` is treated specially as a binder; it does not generate a symbol in the enclosing
scope. So resolving the `_` identifier did not see the enclosing bind and searched
further out instead, until it found the "renamed" import. Beautiful! It shows that
treating wildcards as some sort of identifiers is fraught with surprises.
odersky added a commit to dotty-staging/dotty that referenced this issue Nov 5, 2020
This was a very interesting bug. Why did `any2stringadd` appear out of the blue?
The first observation was that it was resolved by an import of an identifier with
`_` as its name. Why? Because we have a standard predefined import
```scala
import Predef.{any2stringadd => _, _}
```
The correct encoding for the removal `_` is as an empty tree, but by mistake
we generated an import with a `_` ident instead. So this counted as a renaming
of `any2stringadd` to the identifier `_`.

How did we end up with an identifier `_` that needed to be resolved? This was a
second bug in Desugar, method `makeIdPat`. Here we needed to create binds for parts
of a pattern. If the pattern was already a Bind, we used that one instead. But the
`Bind` in question was anonymous, using `_` as the pattern variable. So we did not
replace that by a fresh identifier, but used `_` as the identifier instead. However,
`_` is treated specially as a binder; it does not generate a symbol in the enclosing
scope. So resolving the `_` identifier did not see the enclosing bind and searched
further out instead, until it found the "renamed" import. Beautiful! It shows that
treating wildcards as some sort of identifiers is fraught with surprises.
bishabosha added a commit that referenced this issue Nov 6, 2020
Fix #10178: Put the wildcard demon back in the bottle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants