Skip to content

Commit 9b6d0c0

Browse files
committed
Implement implicit dependent function types
1 parent 7e2e042 commit 9b6d0c0

File tree

4 files changed

+22
-9
lines changed

4 files changed

+22
-9
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,10 +1328,7 @@ object Types {
13281328
val funType = defn.FunctionOf(
13291329
formals1 mapConserve (_.underlyingIfRepeated(mt.isJavaMethod)),
13301330
mt.nonDependentResultApprox, mt.isImplicitMethod && !ctx.erasedTypes)
1331-
if (mt.isDependent) {
1332-
assert(!mt.isImplicitMethod)
1333-
RefinedType(funType, nme.apply, mt)
1334-
}
1331+
if (mt.isDependent) RefinedType(funType, nme.apply, mt)
13351332
else funType
13361333
}
13371334

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -719,12 +719,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
719719
completeParams(params)
720720
val params1 = params.map(typedExpr(_).asInstanceOf[ValDef])
721721
val resultTpt = typed(body)
722-
val mt = MethodType.fromSymbols(params1.map(_.symbol), resultTpt.tpe)
722+
val companion = if (isImplicit) ImplicitMethodType else MethodType
723+
val mt = companion.fromSymbols(params1.map(_.symbol), resultTpt.tpe)
723724
if (mt.isParamDependent)
724725
ctx.error(i"$mt is an illegal function type because it has inter-parameter dependencies", tree.pos)
725-
if (isImplicit)
726-
ctx.error(i"dependent function type $mt may not be implicit", tree.pos)
727-
728726
val resTpt = TypeTree(mt.nonDependentResultApprox).withPos(body.pos)
729727
val typeArgs = params1.map(_.tpt) :+ resTpt
730728
val tycon = TypeTree(funCls.typeRef)
@@ -1723,7 +1721,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
17231721
}
17241722

17251723
protected def makeImplicitFunction(tree: untpd.Tree, pt: Type)(implicit ctx: Context): Tree = {
1726-
val defn.FunctionOf(formals, resType, true) = pt.dealias
1724+
val defn.FunctionOf(formals, _, true) = pt.dealias.dropDependentRefinement
17271725
val paramTypes = formals.map(fullyDefinedType(_, "implicit function parameter", tree.pos))
17281726
val ifun = desugar.makeImplicitFunction(paramTypes, tree)
17291727
typr.println(i"make implicit function $tree / $pt ---> $ifun")

library/src/dotty/DottyPredef.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ object DottyPredef {
3838
final def assertFail(): Unit = throw new java.lang.AssertionError("assertion failed")
3939
final def assertFail(message: => Any): Unit = throw new java.lang.AssertionError("assertion failed: " + message)
4040

41+
@inline final def implicitly[T](implicit ev: T): T = ev
4142
}

tests/pos/depfuntype.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,21 @@ object Test {
1515
val d: C = c
1616
val z = depfun3(d)
1717
val z1: d.M = z
18+
19+
// Reproduced here because the one from DottyPredef is lacking a Tasty tree and
20+
// therefore can't be inlined when testing non-bootstrapped.
21+
// But inlining `implicitly` is vital to make the definition of `ifun` below work.
22+
inline final def implicitly[T](implicit ev: T): T = ev
23+
24+
type IDF = implicit (x: C) => x.M
25+
26+
implicit val ic: C = ???
27+
28+
val ifun: IDF = implicitly[C].m
29+
30+
val u = ifun(c)
31+
val u1: Int = u
32+
33+
val v = ifun(d)
34+
val v1: d.M = v
1835
}

0 commit comments

Comments
 (0)