Skip to content

Commit

Permalink
add DisambiguationFormatter that expand diff form to include type sym…
Browse files Browse the repository at this point in the history
…bol of both sides yield to identical Formatted form

no test yet
  • Loading branch information
tribbloid committed Sep 21, 2023
1 parent 08b6819 commit 96a76cc
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class SplainAnalyzer(val global: Global, val pluginSettings: PluginSettings)
ShapelessRecordItemFormatter,
RefinedFormatterImproved,
// RefinedFormatter,
ByNameFormatter
ByNameFormatter,
DiffDisambiguationFormatter
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,43 @@ trait SplainFormattersExtension extends SplainFormatters {
}
}
}

object DiffDisambiguationFormatter extends SpecialFormatter {

override def apply[A](
tpe: Type,
simple: String,
args: List[A],
formattedArgs: => List[Formatted],
top: Boolean
)(rec: (A, Boolean) => Formatted): Option[Formatted] = None

override def diff(
left: Type,
right: Type,
top: Boolean
): Option[Formatted] = {

val original = formatDiffSimple(left, right)

original match {
case Diff(lf, rf) =>
val sameResult = lf == rf
val easilyMistakable = TypeDiffView(left, right).easilyMistakable

if (left != right && (sameResult || easilyMistakable)) {

val result = Diff(
RefinedForm(lf :: Nil, Simple(SimpleName(s"in ${left.prefix.typeSymbol.fullNameString}")) :: Nil),
RefinedForm(rf :: Nil, Simple(SimpleName(s"in ${right.prefix.typeSymbol.fullNameString}")) :: Nil)
)
Some(result)
} else None

case _ =>
None
}

}
}
}
29 changes: 29 additions & 0 deletions core/src/main/scala-2.13.7+/latest/splain/TyperCompatViews.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,35 @@ trait TyperCompatViews {
}
}

case class TypeDiffView(
found: Type,
req: Type
) {

def map(fn: Type => Type): TypeDiffView =
TypeDiffView(fn(found), fn(req))

def toTuple[T](fn: Type => T): (T, T) = (fn(found), fn(req))

// copied from eponymous variable in Scala compiler
// apparently doesn't work after type arg stripped
lazy val easilyMistakable: Boolean = {

val foundWiden = found.widen
val reqWiden = req.widen
val sameNamesDifferentPrefixes =
foundWiden.typeSymbol.name == reqWiden.typeSymbol.name &&
foundWiden.prefix.typeSymbol != reqWiden.prefix.typeSymbol
val easilyMistakable =
sameNamesDifferentPrefixes &&
!req.typeSymbol.isConstant &&
finalOwners(foundWiden) && finalOwners(reqWiden) &&
!found.typeSymbol.isTypeParameterOrSkolem && !req.typeSymbol.isTypeParameterOrSkolem

easilyMistakable
}
}

case class DivergingImplicitErrorView(self: DivergentImplicitTypeError) {

lazy val errMsg: String = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
newSource1.scala:6: error: type mismatch;
Long {in <none>}|Long {in scala}
else add2(x.head, y.head) :: add(x.tail, y.tail)
^
newSource1.scala:6: error: type mismatch;
Long {in <none>}|Long {in scala}
else add2(x.head, y.head) :: add(x.tail, y.tail)
^
19 changes: 19 additions & 0 deletions core/src/test/scala/splain/plugin/DiffDisambiguationSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package splain.plugin

import splain.SpecBase

class DiffDisambiguationSpec extends SpecBase.Direct {

final val basic =
"""
object Test {
def add2(x:Long,y:Long): Long = x + y
def add[Long](x: List[Long], y: List[Long]): List[Long] =
if (x.isEmpty || y.isEmpty) Nil
else add2(x.head, y.head) :: add(x.tail, y.tail)
}
"""

check(basic, numberOfErrors = 2)
}

0 comments on commit 96a76cc

Please sign in to comment.