Skip to content

Commit 7d3e86b

Browse files
committed
Make normalize handle implicit function types
This is necessary so that we can typecheck the last 4 statements of i2146.scala.
1 parent e258b86 commit 7d3e86b

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,8 @@ object ProtoTypes {
422422

423423
/** The normalized form of a type
424424
* - unwraps polymorphic types, tracking their parameters in the current constraint
425-
* - skips implicit parameters; if result type depends on implicit parameter,
426-
* replace with Wildcard.
425+
* - skips implicit parameters of methods and functions;
426+
* if result type depends on implicit parameter, replace with fresh type dependent parameter.
427427
* - converts non-dependent method types to the corresponding function types
428428
* - dereferences parameterless method types
429429
* - dereferences nullary method types provided the corresponding function type
@@ -437,9 +437,10 @@ object ProtoTypes {
437437
*/
438438
def normalize(tp: Type, pt: Type)(implicit ctx: Context): Type = Stats.track("normalize") {
439439
tp.widenSingleton match {
440-
case poly: PolyType => normalize(constrained(poly).resultType, pt)
440+
case poly: PolyType =>
441+
normalize(constrained(poly).resultType, pt)
441442
case mt: MethodType =>
442-
if (mt.isImplicit) resultTypeApprox(mt)
443+
if (mt.isImplicit) normalize(resultTypeApprox(mt), pt)
443444
else if (mt.isDependent) tp
444445
else {
445446
val rt = normalize(mt.resultType, pt)
@@ -451,8 +452,11 @@ object ProtoTypes {
451452
if (mt.paramInfos.nonEmpty || ft <:< pt) ft else rt
452453
}
453454
}
454-
case et: ExprType => et.resultType
455-
case _ => tp
455+
case et: ExprType =>
456+
normalize(et.resultType, pt)
457+
case wtp =>
458+
if (defn.isImplicitFunctionType(wtp)) normalize(wtp.dealias.argInfos.last, pt)
459+
else tp
456460
}
457461
}
458462

tests/pos/i2146.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
(A(),B())
2+
(A(),B())
3+
(A(),B())
4+
A()
5+
(A(),B())
6+
(A(),B())

tests/pos/i2146.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
object Test {
2+
case class A()
3+
case class B()
4+
5+
def simple[A]: implicit A => A = implicitly[A]
6+
7+
def foo[A, B]: implicit A => implicit B => (A, B) =
8+
(implicitly[A], implicitly[B])
9+
10+
implicit val a: A = A()
11+
implicit val b: B = B()
12+
13+
def main(args: Array[String]) = {
14+
println(foo[A, B])
15+
println(foo[A, B](a))
16+
println(foo(a)(b))
17+
val s: implicit A => A = simple[A]
18+
println(s)
19+
val x0: implicit A => implicit B => (A, B) = foo[A, B]
20+
println(x0)
21+
val x1: implicit B => (A, B) = foo[A, B]
22+
println(x1)
23+
}
24+
}

0 commit comments

Comments
 (0)