aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-04-22 11:55:36 +0200
committerMartin Odersky <odersky@gmail.com>2016-04-22 12:06:31 +0200
commit89f9091c2d10aa23c5d6259694df104fc14c60f7 (patch)
treeb78bab097099c5b4fa8a62fe422419227a4adf07 /src
parent320ca51f0226cf61dfa6d882d30de15ab221f07b (diff)
downloaddotty-89f9091c2d10aa23c5d6259694df104fc14c60f7.tar.gz
dotty-89f9091c2d10aa23c5d6259694df104fc14c60f7.tar.bz2
dotty-89f9091c2d10aa23c5d6259694df104fc14c60f7.zip
Support implicitNotFound annotation
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala2
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala12
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala11
3 files changed, 24 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 5376ed591..9128bd3a5 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -449,6 +449,8 @@ class Definitions {
def ContravariantBetweenAnnot(implicit ctx: Context) = ContravariantBetweenAnnotType.symbol.asClass
lazy val DeprecatedAnnotType = ctx.requiredClassRef("scala.deprecated")
def DeprecatedAnnot(implicit ctx: Context) = DeprecatedAnnotType.symbol.asClass
+ lazy val ImplicitNotFoundAnnotType = ctx.requiredClassRef("scala.annotation.implicitNotFound")
+ def ImplicitNotFoundAnnot(implicit ctx: Context) = ImplicitNotFoundAnnotType.symbol.asClass
lazy val InvariantBetweenAnnotType = ctx.requiredClassRef("dotty.annotation.internal.InvariantBetween")
def InvariantBetweenAnnot(implicit ctx: Context) = InvariantBetweenAnnotType.symbol.asClass
lazy val MigrationAnnotType = ctx.requiredClassRef("scala.annotation.migration")
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index d6a87acf6..69c12e5f5 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -116,6 +116,18 @@ object ErrorReporting {
| found : $found
| required: $expected""".stripMargin + whyNoMatchStr(found, expected)
}
+
+ /** Format `raw` implicitNotFound argument, replacing all
+ * occurrences of `${X}` where `X` is in `paramNames` with the
+ * corresponding shown type in `args`.
+ */
+ def implicitNotFoundString(raw: String, paramNames: List[String], args: List[Type]): String = {
+ def translate(name: String): Option[String] = {
+ val idx = paramNames.indexOf(name)
+ if (idx >= 0) Some(args(idx).show) else None
+ }
+ """\$\{\w*\}""".r.replaceSomeIn(raw, m => translate(m.matched.drop(2).init))
+ }
}
def err(implicit ctx: Context): Errors = new Errors
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index b95acc7ca..f263d3093 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -1541,7 +1541,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case failure: SearchFailure =>
val arg = synthesizedClassTag(formal)
if (!arg.isEmpty) arg
- else implicitArgError(d"no implicit argument of type $formal found for $where" + failure.postscript)
+ else {
+ var msg = d"no implicit argument of type $formal found for $where" + failure.postscript
+ for (notFound <- formal.typeSymbol.getAnnotation(defn.ImplicitNotFoundAnnot);
+ Literal(Constant(raw: String)) <- notFound.argument(0))
+ msg = err.implicitNotFoundString(
+ raw,
+ formal.typeSymbol.typeParams.map(_.name.unexpandedName.toString),
+ formal.argInfos)
+ implicitArgError(msg)
+ }
}
}
if (errors.nonEmpty) {