Skip to content

Commit

Permalink
reporting ignored overloaded specs
Browse files Browse the repository at this point in the history
Summary:
- when a function literal is used (like `fun foo/1`) and the corresponding function has overloaded specs, we elaborate the type of such expression as `dynamic() -> dynamic()`, since overloaded specs are not the part of "language of types"
- adding an option to introspect such approximations

Reviewed By: VLanvin

Differential Revision: D62641981

fbshipit-source-id: 1d7d3c3452640510a4b49acdc99f5d5768ce7bd8
  • Loading branch information
ilya-klyuchnikov authored and facebook-github-bot committed Sep 16, 2024
1 parent 931e328 commit ea1084a
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 3 deletions.
2 changes: 2 additions & 0 deletions eqwalizer/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ eqwalizer {
overloaded_spec_dynamic_result = ${?EQWALIZER_OVERLOADED_SPEC_DYNAMIC_RESULT}
custom_maps_merge = false
custom_maps_merge = ${?EQWALIZER_CUSTOM_MAPS_MERGE}
ignored_overloaded_spec = false
ignored_overloaded_spec = ${?EQWALIZER_IGNORED_OVERLOADED_SPEC}
}
2 changes: 2 additions & 0 deletions eqwalizer/src/main/scala/com/whatsapp/eqwalizer/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ package object eqwalizer {
customMapsMerge: Boolean,
mode: Mode.Mode,
errorDepth: Int,
ignoredOverloadedSpec: Boolean,
)

lazy val config: Config = {
Expand All @@ -52,6 +53,7 @@ package object eqwalizer {
customMapsMerge = config.getBoolean("custom_maps_merge"),
mode,
errorDepth = config.getInt("error_depth"),
ignoredOverloadedSpec = config.getBoolean("ignored_overloaded_spec"),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,20 @@ final class Check(pipelineContext: PipelineContext) {
}
env2
case LocalFun(id) =>
val ft = util.getFunType(module, id)
val fqn = util.globalFunId(module, id)
if (pipelineCtx.ignoredOverloadedSpec && util.getOverloadedSpec(fqn).isDefined) {
diagnosticsInfo.add(IgnoredOverloadedSpec(expr.pos))
}
val ft = util.getFunType(fqn)
val ft1 = freshen(ft)
if (!subtype.subType(ft1, resTy))
diagnosticsInfo.add(ExpectedSubtype(expr.pos, expr, expected = resTy, got = ft1))
env
case RemoteFun(fqn) =>
val ft = util.getFunType(fqn)
if (pipelineCtx.ignoredOverloadedSpec && util.getOverloadedSpec(fqn).isDefined) {
diagnosticsInfo.add(IgnoredOverloadedSpec(expr.pos))
}
val ft1 = freshen(ft)
if (!subtype.subType(ft1, resTy))
diagnosticsInfo.add(ExpectedSubtype(expr.pos, expr, expected = resTy, got = ft1))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,17 @@ final class Elab(pipelineContext: PipelineContext) {
(resTy, env1)
}
case LocalFun(id) =>
val ft = util.getFunType(module, id)
val fqn = util.globalFunId(module, id)
if (pipelineCtx.ignoredOverloadedSpec && util.getOverloadedSpec(fqn).isDefined) {
diagnosticsInfo.add(IgnoredOverloadedSpec(expr.pos))
}
val ft = util.getFunType(fqn)
(check.freshen(ft), env)
case RemoteFun(fqn) =>
val ft = util.getFunType(fqn)
if (pipelineCtx.ignoredOverloadedSpec && util.getOverloadedSpec(fqn).isDefined) {
diagnosticsInfo.add(IgnoredOverloadedSpec(expr.pos))
}
(check.freshen(ft), env)
case lambda @ Lambda(clauses) =>
val arity = clauses.head.pats.length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ object TcDiagnostics {
}
case class IgnoredOverloadedSpec(pos: Pos) extends TypeError {
override val msg: String = s"dynamic() -> dynamic() is used"
def errorName = "not_enough_info_to_branch"
def errorName = "ignored_overloaded_spec"
override def erroneousExpr: Option[Expr] = None
}
case class LambdaArityMismatch(pos: Pos, expr: Expr, lambdaArity: Int, argsArity: Int) extends TypeError {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@ package object tc {
val clauseCoverage: Boolean = config.clauseCoverage
val overloadedSpecDynamicResult: Boolean = config.overloadedSpecDynamicResult
val customMapsMerge: Boolean = config.customMapsMerge
val ignoredOverloadedSpec: Boolean = config.ignoredOverloadedSpec
}
}

0 comments on commit ea1084a

Please sign in to comment.