aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/typer
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2017-03-09 10:16:51 +0100
committerGitHub <noreply@github.com>2017-03-09 10:16:51 +0100
commitbf9bdae2c2affd9a5f3e68a372c8ad3edd4ba29e (patch)
tree1beacdd84bf4b37b7472561d811931bf693289d3 /compiler/src/dotty/tools/dotc/typer
parent391aaa1d8a5880bbc64679760a5623460e9f936f (diff)
parentaa2f9078d76a21d828a06b8e324d31a502ee505c (diff)
downloaddotty-bf9bdae2c2affd9a5f3e68a372c8ad3edd4ba29e.tar.gz
dotty-bf9bdae2c2affd9a5f3e68a372c8ad3edd4ba29e.tar.bz2
dotty-bf9bdae2c2affd9a5f3e68a372c8ad3edd4ba29e.zip
Merge pull request #2065 from dotty-staging/change-implicit-conv2
Disallow subtypes of Function1 acting as implicit conversions
Diffstat (limited to 'compiler/src/dotty/tools/dotc/typer')
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala28
1 files changed, 23 insertions, 5 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index 759cc62e9..ebbcbcc95 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -82,11 +82,29 @@ object Implicits {
case tpw: TermRef =>
false // can't discard overloaded refs
case tpw =>
- //if (ctx.typer.isApplicable(tp, argType :: Nil, resultType))
- // println(i"??? $tp is applicable to $this / typeSymbol = ${tpw.typeSymbol}")
- !tpw.derivesFrom(defn.FunctionClass(1)) ||
- ref.symbol == defn.Predef_conforms //
- // as an implicit conversion, Predef.$conforms is a no-op, so exclude it
+ // Only direct instances of Function1 and direct or indirect instances of <:< are eligible as views.
+ // However, Predef.$conforms is not eligible, because it is a no-op.
+ //
+ // In principle, it would be cleanest if only implicit methods qualified
+ // as implicit conversions. We could achieve that by having standard conversions like
+ // this in Predef:
+ //
+ // implicit def convertIfConforms[A, B](x: A)(implicit ev: A <:< B): B = ev(a)
+ // implicit def convertIfConverter[A, B](x: A)(implicit ev: ImplicitConverter[A, B]): B = ev(a)
+ //
+ // (Once `<:<` inherits from `ImplicitConverter` we only need the 2nd one.)
+ // But clauses like this currently slow down implicit search a lot, because
+ // they are eligible for all pairs of types, and therefore are tried too often.
+ // We emulate instead these conversions directly in the search.
+ // The reason for leaving out `Predef_conforms` is that we know it adds
+ // nothing since it only relates subtype with supertype.
+ //
+ // We keep the old behavior under -language:Scala2.
+ val isFunctionInS2 = ctx.scala2Mode && tpw.derivesFrom(defn.FunctionClass(1))
+ val isImplicitConverter = tpw.derivesFrom(defn.Predef_ImplicitConverter)
+ val isConforms =
+ tpw.derivesFrom(defn.Predef_Conforms) && ref.symbol != defn.Predef_conforms
+ !(isFunctionInS2 || isImplicitConverter || isConforms)
}
def discardForValueType(tpw: Type): Boolean = tpw match {