aboutsummaryrefslogtreecommitdiff
path: root/compiler/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-03-08 22:06:22 +0100
committerMartin Odersky <odersky@gmail.com>2017-03-08 22:06:35 +0100
commitaa2f9078d76a21d828a06b8e324d31a502ee505c (patch)
treebf657e58c1a78357349def2309dd41c0cecdd9a1 /compiler/src
parent180dfdc7e81d632e599fb0a545025720e8000573 (diff)
downloaddotty-aa2f9078d76a21d828a06b8e324d31a502ee505c.tar.gz
dotty-aa2f9078d76a21d828a06b8e324d31a502ee505c.tar.bz2
dotty-aa2f9078d76a21d828a06b8e324d31a502ee505c.zip
Drop special case around Function1
Now only Scala2 mode treats Function1's as implicit conversions. Instead we introduce a new subclass ImplicitConverter of Function1, instances of which are turned into implicit conversions.
Diffstat (limited to 'compiler/src')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala30
2 files changed, 12 insertions, 20 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index fcbb2f974..1be47c1da 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -338,6 +338,8 @@ class Definitions {
def DottyPredefModule(implicit ctx: Context) = DottyPredefModuleRef.symbol
def Predef_eqAny(implicit ctx: Context) = DottyPredefModule.requiredMethod(nme.eqAny)
+ lazy val Predef_ImplicitConverterR = DottyPredefModule.requiredClass("ImplicitConverter").typeRef
+ def Predef_ImplicitConverter(implicit ctx: Context) = Predef_ImplicitConverterR.symbol
lazy val DottyArraysModuleRef = ctx.requiredModuleRef("dotty.runtime.Arrays")
def DottyArraysModule(implicit ctx: Context) = DottyArraysModuleRef.symbol
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index 6dbb2216c..ebbcbcc95 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -86,35 +86,25 @@ object Implicits {
// 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. The reasons for deviating are as follows:
- // Keeping Function1: It's still used quite often (for instance, view
- // bounds map to implicits of function types) and there is no feasible workaround.
- // One tempting workaround would be to add a global def
- //
- // implicit def convertIfFuntion1[A, B](x: A)(implicit ev: A => B): B = ev(a)
- //
- // But that would throw out the baby with the bathwater. Now, every subtype of
- // function gives again rise to an implicit conversion. So it's better to just accept
- // function types in their dual roles.
- //
- // The reason for the treatment of <:< and conforms is similar. We could
- // avoid the clause by having a standard conversion like this in Predef:
+ // 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)
//
- // But that would slow down implicit search a lot, because this conversion is
- // eligible for all pairs of types, and therefore is tried a lot. So we
- // emulate the existence of a such a conversion directly in the search.
+ // (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 isFunction =
- if (ctx.scala2Mode) tpw.derivesFrom(defn.FunctionClass(1))
- else tpw.isRef(defn.FunctionClass(1))
+ 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
- !(isFunction || isConforms)
+ !(isFunctionInS2 || isImplicitConverter || isConforms)
}
def discardForValueType(tpw: Type): Boolean = tpw match {