Skip to content

Commit f0d3487

Browse files
committed
Adding checks for implicit definitions
1) Result type may not be empty 2) Parameters of implicit conversions may not be singletons Reason for 2) is that we can do a much better caching for eligible implicits if we can widen singleton arguments in ViewProto. This leads to consicderable speedups in implicit search which seem to be hard to get without the restriction.
1 parent 20c0a6a commit f0d3487

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/dotty/tools/dotc/typer/Inferencing.scala

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,28 @@ object Inferencing {
425425
checkStable(tp.prefix, pos)
426426
tp
427427
case _ =>
428-
ctx.error(s"$tp is not a class type", pos)
428+
ctx.error(i"$tp is not a class type", pos)
429429
defn.ObjectClass.typeRef
430430
}
431431

432+
/** Check that (return) type of implicit definition is not empty */
433+
def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = defTree.tpt match {
434+
case TypeTree(original) if original.isEmpty =>
435+
val resStr = if (defTree.isInstanceOf[untpd.DefDef]) "result " else ""
436+
ctx.error(i"${resStr}type of implicit definition needs to be given explicitly", defTree.pos)
437+
case _ =>
438+
}
439+
440+
/** Check that a non-implicit parameter making up the first parameter section of an
441+
* implicit conversion is not a singleton type.
442+
*/
443+
def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = vparamss match {
444+
case (vparam :: Nil) :: _ if !(vparam.symbol is Implicit) =>
445+
if (vparam.tpt.tpe.isInstanceOf[SingletonType])
446+
ctx.error(s"implicit conversion may not have a parameter of singleton type", vparam.tpt.pos)
447+
case _ =>
448+
}
449+
432450
/** Ensure that first typeref in a list of parents points to a non-trait class.
433451
* If that's not already the case, add one.
434452
*/

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,7 @@ class Typer extends Namer with Applications with Implicits {
862862
val ValDef(mods, name, tpt, rhs) = vdef
863863
val mods1 = typedModifiers(mods)
864864
val tpt1 = typedType(tpt)
865+
if (sym is Implicit) checkImplicitTptNonEmpty(vdef)
865866
val rhs1 = rhs match {
866867
case Ident(nme.WILDCARD) => rhs withType tpt1.tpe
867868
case _ => typedExpr(rhs, tpt1.tpe)
@@ -875,6 +876,10 @@ class Typer extends Namer with Applications with Implicits {
875876
val mods1 = typedModifiers(mods)
876877
val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef])
877878
val vparamss1 = vparamss nestedMapconserve (typed(_).asInstanceOf[ValDef])
879+
if (sym is Implicit) {
880+
checkImplicitTptNonEmpty(ddef)
881+
checkImplicitParamsNotSingletons(vparamss1)
882+
}
878883
val tpt1 = typedType(tpt)
879884
val rhs1 = typedExpr(rhs, tpt1.tpe)
880885
cpy.DefDef(ddef, mods1, name, tparams1, vparamss1, tpt1, rhs1).withType(sym.termRefWithSig)

0 commit comments

Comments
 (0)