Re: [scala-user] Recursive typeclasses + Nothing = diverging-implicit-expansion? Any way around that?

77 views
Skip to first unread message

Jason Zaugg

unread,
May 24, 2014, 4:03:06 PM5/24/14
to Som Snytt, Haoyi Li, scala-i...@googlegroups.com
[moving to scala-internals]

If you also want some practice at watching types flow through the innards of the compiler, set your breakpoint in this method.

-jason
    /** Retract arguments that were inferred to Nothing because inference failed. Correct types for repeated params.
     *
     * We detect Nothing-due-to-failure by only retracting a parameter if either:
     *  - it occurs in an invariant/contravariant position in `restpe`
     *  - `restpe == WildcardType`
     */

    def adjustTypeArgs(tparams: List[Symbol], tvars: List[TypeVar], targs: List[Type], restpe: Type = WildcardType): AdjustedTypeArgs.Result  = {
      val buf = AdjustedTypeArgs.Result.newBuilder[Symbol, Option[Type]]

      foreach3(tparams, tvars, targs) { (tparam, tvar, targ) =>
        val retract = (
              targ.typeSymbol == NothingClass                                         // only retract Nothings
          && (restpe.isWildcard || !varianceInType(restpe)(tparam).isPositive)  // don't retract covariant occurrences
        )

        buf += ((tparam,
          if (retract) None
          else Some(
             ...
          )
        ))
      }
      buf.result()
    }


On Sat, May 24, 2014 at 9:35 PM, Som Snytt <som....@gmail.com> wrote:
This or similar just came up on SO.  I meant to get back to it later for further practice in reading typer-debug.  For one thing, you never know whether that it works a certain way is a bug, a limitation or a best practice.  But it helps to have an authoritative thread on scala-user.


On Sat, May 24, 2014 at 11:53 AM, Jason Zaugg <jza...@gmail.com> wrote:
On Sat, May 24, 2014 at 8:43 PM, Haoyi Li <haoy...@gmail.com> wrote:
Here's another example, not sure if it's the same as I'm seeing in uPickle, where an implicit should (I think) be found but isn't.



class TC[T](val name: String) def thing[T: TC](t: => T) = implicitly[TC[T]].name
implicit def tcNothing: TC[Nothing] = new TC[Nothing]("tcNothing")
implicit def tcSeq[T: TC]: TC[Seq[T]] = new TC[Seq[T]]("tcSeq:" + thing[T](???))
println(thing(???)) // compiles println(thing(Seq())) // does not compile

The gist of the workaround I allused to is that you can to provide an implicit for TC[Seq[Nothing]] explicitly, in addition to [T] TC[T] => TC[Seq[T]].

The problem is that when the compiler infers a type as Nothing, it retracts that so that it might infer something more specific at a later juncture. Sorry this is a bit of a vague explanation, I need to find some time to trace out the flow of inference and implicit search to explain it more clearly.

-jason

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Reply all
Reply to author
Forward
0 new messages