tek / splain

better implicit errors for scala
MIT License
370 stars 29 forks source link

possibly odd output #10

Closed drdozer closed 7 years ago

drdozer commented 7 years ago

I've given splain a go on a project where I'm having problems with implicits. Here is some of the output:

[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/TestEnc.scala:46: implicit error;
[error] !I e: RdfTagless[Prod]
[error]     implicitly[RdfTagless[Prod[cats.Id, Encoding, ?]]]

The unaltered output is:

[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/TestEnc.scala:46: could not find implicit value for parameter e: uk.co.turingatemyhamster.trefoil.RdfTagless[[γ$1$]cats.data.Prod[[A]A,uk.co.turingatemyhamster.trefoil.Encoding,γ$1$]]
[error]     implicitly[RdfTagless[Prod[cats.Id, Encoding, ?]]]

Perhaps I'm reading it wrong, but it looks to me like the splain output is trunchating the printing of Prod.

Related to this, what I really need to understand what's going wrong is what implicits it tried here but failed to use. In a verbose output, I really want to see a list of all the failed candidate implicits with why they failed to match. I only really need that for the deepest failing implicit in the chain. Is that possible?

tek commented 7 years ago

yep, some formatting rules are still missing, in which case only the type constructor name is shown. I'll give it a look at the weekend.

Regarding the second part, if no deeper implicits are shown, then no candidate has been tried, because none had a matching shape. In that case, the search doesn't log any error, so the plugin can't do anything. If you'd inspect the output of compilation with -Xlog-implicits and find additional info that isn't shown, please report.

tek commented 7 years ago

please verify that 0.1.21 fixes this!

drdozer commented 7 years ago

Yes :) I can confirm this fixes it in my code.

drdozer commented 7 years ago

Not quite -- still have one case (of 4) where it's just printing Prod

    val objects = Eval get rainbowKb[cats.Id]
    println(s"Object model:\n$objects")

    val prettyPrinted = Eval get rainbowKb[Const[List[String], ?]]
    println(s"Pretty Print:\n$prettyPrinted")

    val longEncoded = Eval get rainbowKb[Encoding]
    println(s"Long encoding:\n$longEncoded")

    type t[X] = Prod[cats.Id, Encoding, X] // have to use this -- see productEncoding for a failing case
    val someEncoding = Eval.get(rainbowKb[t])
    println(s"Combined encoding:\n$someEncoding")

    val prettyPrintedFromObjects = Replay(objects).evalAt[Const[List[String], ?]]
    println(s"Pretty Print from object replay:\n$prettyPrintedFromObjects")

    implicitly[RdfTagless[Prod[cats.Id, Encoding, ?]]]

    val penc = rainbowKb[Prod[cats.Id, Encoding, ?]]

    implicitly[Eval.AsAux[t, RdfCore.Graph, (RdfCore.Graph, Set[LongEncodedTriple])]]
    implicitly[Eval.AsAux[Prod[cats.Id, Encoding, ?], RdfCore.Graph, (RdfCore.Graph, Set[LongEncodedTriple])]]
    Eval.evalProd[cats.Id, Encoding, RdfCore.Graph, RdfCore.Graph, Set[LongEncodedTriple]]

    // using the Product type directly fails -- see t[X] above for type-alias that works(ish)
    val productEncoding = Eval.get(rainbowKb[Prod[cats.Id, Encoding, ?]](RdfTagless.fromAux2[Prod, cats.Id, Encoding]))
    println(s"Combined encoding:\n$productEncoding")

    // fixme: Doesn't work - ?Rep[?S] isn't currying at all here for the nested case
    type u[X] = Prod[Const[List[String], ?], t, X]
    val allEncoding = Eval.get(rainbowKb[u])
    println(s"Combined encoding:\n$allEncoding")
[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/TestEnc.scala:49: implicit error;
[error] !I e: RdfTagless[Prod[A, Encoding, ?]]                                                                                                             
[error]     implicitly[RdfTagless[Prod[cats.Id, Encoding, ?]]]                                                                                             
[error]               ^                                                                                                                                    
[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/TestEnc.scala:51: implicit error;                     
[error] !I R: RdfTagless[Prod[A, Encoding, ?]]                                                                                                             
[error]     val penc = rainbowKb[Prod[cats.Id, Encoding, ?]]                                                                                               
[error]                         ^                                                                                                                          
[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/TestEnc.scala:54: implicit error;                     
[error] !I e: As[Prod[A, Encoding, ?], Graph] {type T = (Graph,Set[LongEncodedTriple])}                                                                    
[error]     implicitly[Eval.AsAux[Prod[cats.Id, Encoding, ?], RdfCore.Graph, (RdfCore.Graph, Set[LongEncodedTriple])]]                                     
[error]               ^                                                                                                                                    
[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/TestEnc.scala:58: overloaded method value get with alternatives:                                                                                                                                                 
[error]   [Rep[_, _], S0, S, T](s: Rep[S0,S])(implicit AsU: uk.co.turingatemyhamster.trefoil.AsAuxUnapply[Rep,S0,S,T])T <and>                              
[error]   [Rep[_], S, T](s: Rep[S])(implicit As: uk.co.turingatemyhamster.trefoil.Eval.AsAux[Rep,S,T])T                                                    
[error]  cannot be applied to (cats.data.Prod[[A]A,uk.co.turingatemyhamster.trefoil.Encoding,uk.co.turingatemyhamster.trefoil.RdfCore.Graph])              
[error]     val productEncoding = Eval.get(rainbowKb[Prod[cats.Id, Encoding, ?]](RdfTagless.fromAux2[Prod, cats.Id, Encoding]))                            
[error]                                ^                                                                                                                   
[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/TestEnc.scala:63: implicit error;                     
[error] !I R: RdfTagless[Prod]                                                                                                                             
[error]     val allEncoding = Eval.get(rainbowKb[u])                                                                                                       
[error]                                         ^                                                                                                          
[error] 5 errors found                          

I will see if I can minimise this.

drdozer commented 7 years ago

OK, this is a lot smaller:

object ProdMin {
  def main(args: Array[String]): Unit = {
    trait Encoding[A]
    trait RdfTagless[Rep[_]]
    def rainbowKb[R[_]](implicit R: RdfTagless[R]) = ???
    type t[X] = Prod[cats.Id, Encoding, X]
    type u[X] = Prod[Const[List[String], ?], t, X]
    rainbowKb[u]
  }
}
5. Waiting for source changes... (press enter to interrupt)
[info] Compiling 2 Scala sources to /home/nmrp3/devel/turingatemyhamster/trefoil/target/scala-2.12/classes...
[error] /home/nmrp3/devel/turingatemyhamster/trefoil/src/main/scala/uk/co/turingatemyhamster/trefoil/ProdMin.scala:11: implicit error;
[error] !I R: RdfTagless[Prod]
[error]     rainbowKb[u]
tek commented 7 years ago

alright, I'll take a look!

tek commented 7 years ago

so. this was rather complicated, but it looks pretty well now. There is one trade-off, however – the type constructors of type aliases with parameters don't get dealiased anymore, because it would represent Id as A…not sure what's the better alternative, will have to use it and see.

drdozer commented 7 years ago

Great. In 0.1.22 I'm now getting a useful type for this corner case and still seeing useful errors for the rest.

tek commented 7 years ago

awesome!