scala / bug

Scala 2 bug reports only. Please, no questions β€” proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

Implicit search doesn't include enclosing prefixes of stable non-static paths #11886

Open lihaoyi opened 4 years ago

lihaoyi commented 4 years ago

Example in 2.13.1:

Welcome to the Ammonite Repl 2.0.4 (Scala 2.13.1 Java 11.0.2)
@ {
  trait Foo{
    object Bar{ def foo(x: Qux) = ??? }
    trait Qux
    implicit def conv(s: String): Qux = ???
  }
  object f extends Foo; f.Bar.foo("hello")
  }
scala.NotImplementedError: an implementation is missing

@ {
  trait Foo{
    object Bar{ def foo(x: Qux) = ??? }
    trait Qux
    implicit def conv(s: String): Qux = ???
  }
  def f(f: Foo) =  f.Bar.foo("hello")
  }
cmd1.sc:6: type mismatch;
 found   : String("hello")
 required: f.Qux
def f(f: Foo) =  f.Bar.foo("hello")
                           ^
Compilation Failed

I would expect both examples to compile, but only the first one with object f extends Foo compiles while the second one with f: Foo as a parameter fails. @smarter says that this works in Dotty, so I assume it's a bug in the Scala 2 compiler.

Moving the implicit conv into the a companion object of Qux makes it get discovered in either case, but that doesn't work for me because the companion object is final and I need to override it in different subclasses of Foo (hence this whole trait thing in the first place)

I bumped into this trying to move all Scalatags implicits into the default implicit scope, to remove the need for wholesale import module._ statements and improve the tidyness of local scope.

Scalatags uses this module-as-function-parameter pattern to allow sharing HTML templates between a generating textual Strings, modules generating live dom.Elements in the browser via Scala.js, and a module generating scalatags.VirtualDom elements of arbitrary types (e.g. React nodes, Preact nodes) on either Scala-JVM and Scala.js.

neko-kai commented 4 years ago

It's unlikely this will be fixed before Scala 3. I would be surprised if this is the first issue on this, I've encountered this weird rule many times: basically, in Scala 2, objects are part of their own implicit scope, but the same does not apply to vals. shapeless tells users to implement shapeless.Poly as objects, not vals because of this limitation

joroKr21 commented 4 years ago

Hmm that is interesting. I was reading the spec a bit closer.

if 𝑇 is a type projection 𝑆#π‘ˆ, the parts of 𝑆 as well as 𝑇 itself;

If we consider f.Bar =:= f.type#Bar then that would include f.type and Bar

if 𝑇 is a singleton type 𝑝.type, the parts of the type of 𝑝;

But the type of f: Foo which would mean Foo#Qux and not f.Qux. Notice how we lost the path dependent type when we widened f. How does dotty handle this?