Scala Programming Language
  1. Scala Programming Language
  2. SI-3346

the implicit arguments of implicit conversions do not guide type inference

    Details

      Description

      object Test {
        class Rep[T](x : T)
       
        class SomeOps[T](x : Rep[T]) { def foo = 1 }
        implicit def mkOps[X, T](x : X)(implicit conv: X => Rep[T]) : SomeOps[T] = new SomeOps(conv(x))
      
        val a: Rep[Int] = error("")
        a.foo // infers mkOps(a).foo but rejects it because the types don't work out
      // mkOps(a) will have type SomeOps[T] where T hasn't been instantiated because 
      // the implicit search for mkOps's implicit argument hasn't been performed yet
      }
      

      relevant code from Implicits.scala

          /** The type parameters to instantiate */
          val undetParams = if (isView) List() else context.outer.undetparams // TODO: why the empty list for a view? why is this a val?
      
                if (itree2.tpe.isError) SearchFailure
                else if (hasMatchingSymbol(itree1)) {
                  val tvars = undetParams map freshVar
                  println("matchesPt??: "+(undetParams, context.undetparams, context.outer.undetparams)) // note that they are different!
                  if (matchesPt(itree2.tpe /* itree2.tpe may contain typeparams from context.undetparams that will get instantiated later (during 2nd-order implicit search)*/, 
                    pt.instantiateTypeParams(undetParams, tvars), undetParams)) {
      
      1. tvars.txt
        115 kB
        Paul Phillips

        Issue Links

          Activity

          Hide
          Paul Phillips added a comment -

          "Do you think that justifies potential breakages?"

          I no longer have an opinion on such tradeoffs.

          Show
          Paul Phillips added a comment - "Do you think that justifies potential breakages?" I no longer have an opinion on such tradeoffs.
          Hide
          Eugene Burmako added a comment - - edited

          @Hubert I'm sorry if I seemed overeager. The right formulation would be "does the general approach outlined in the patch linked above look okay, or I'm overlooking something essential?".

          The divergence test failure does make sense. Previously the offending views were selected by implicit search and then subsequent typechecking caused resolution of their implicit parameters, which led to divergence. Now divergence happens during implicit search, which simply invalidates given views and the error says "expected X, got Y" meaning that no suitable implicit conversions were found. At a glance this makes sense to me. Does it to you?

          Show
          Eugene Burmako added a comment - - edited @Hubert I'm sorry if I seemed overeager. The right formulation would be "does the general approach outlined in the patch linked above look okay, or I'm overlooking something essential?". The divergence test failure does make sense. Previously the offending views were selected by implicit search and then subsequent typechecking caused resolution of their implicit parameters, which led to divergence. Now divergence happens during implicit search, which simply invalidates given views and the error says "expected X, got Y" meaning that no suitable implicit conversions were found. At a glance this makes sense to me. Does it to you?
          Hide
          Paolo G. Giarrusso added a comment -

          Eugene, I'd like to offer a long +1 to (carefully reviewed) breaking changes here. I know you weren't asking me, but I think I can contribute my 2 cents here.

          The following has some assumption on the change: it should make the actual Scalac behavior simpler to describe. Try documenting the current behavior (bugs included), try documenting the behavior with the patch, verify the latter is much simpler and actually understandable; in particular, the latter should be more declarative.

          Because of such bugs, Scalac typechecker's behavior feels random. To see a discussion of them, look no further than this blog post:
          http://yz.mit.edu/wp/true-scala-complexity/

          (I also wonder whether something in there has to do with this bug, maybe seq2richseq? There's a comment from Adriaan Moors about another relation. But don't take me too seriously here, the details are a vague recollection from ages ago; my point is about why such bugs are bad).

          Moreover, it seems that the code which will break is (arguably) buggy anyway, even though without a fixed Scalac this is probably hard to see.

          And changes which fix implicit resolution and break code have gone in as late as 2.10 (IIRC). If wanted, one could support the transition somehow: make the new behavior optional and controlled by an option, or add a warning in 2.11 for code which will break (hard) and make the change for 2.12 (though I'd like things to go faster).

          Overall, I think we need a way to fix bugs which make (buggy) code compile. C++ compilers often broke buggy code, I don't think Scala needs better bug-to-bug compatibility.

          (Sorry for the length).

          Show
          Paolo G. Giarrusso added a comment - Eugene, I'd like to offer a long +1 to (carefully reviewed) breaking changes here. I know you weren't asking me, but I think I can contribute my 2 cents here. The following has some assumption on the change: it should make the actual Scalac behavior simpler to describe. Try documenting the current behavior (bugs included), try documenting the behavior with the patch, verify the latter is much simpler and actually understandable; in particular, the latter should be more declarative. Because of such bugs, Scalac typechecker's behavior feels random. To see a discussion of them, look no further than this blog post: http://yz.mit.edu/wp/true-scala-complexity/ (I also wonder whether something in there has to do with this bug, maybe seq2richseq? There's a comment from Adriaan Moors about another relation. But don't take me too seriously here, the details are a vague recollection from ages ago; my point is about why such bugs are bad). Moreover, it seems that the code which will break is (arguably) buggy anyway, even though without a fixed Scalac this is probably hard to see. And changes which fix implicit resolution and break code have gone in as late as 2.10 (IIRC). If wanted, one could support the transition somehow: make the new behavior optional and controlled by an option, or add a warning in 2.11 for code which will break (hard) and make the change for 2.12 (though I'd like things to go faster). Overall, I think we need a way to fix bugs which make (buggy) code compile. C++ compilers often broke buggy code, I don't think Scala needs better bug-to-bug compatibility. (Sorry for the length).
          Show
          Eugene Burmako added a comment - https://github.com/scala/scala/pull/2822
          Show
          Eugene Burmako added a comment - https://github.com/scala/scala/commit/210dbc7887bc42eed4154de65d0ff5f46ca5ee58

            People

            • Assignee:
              Eugene Burmako
              Reporter:
              Adriaan Moors
              TracCC:
              Andreas Flierl, Daniel Sobral, Ismael Juma, Jason Zaugg, Johannes Rudolph, Mark Harrah, Seth Tisue
            • Votes:
              17 Vote for this issue
              Watchers:
              28 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development