File tree Expand file tree Collapse file tree 2 files changed +56
-3
lines changed
compiler/src/dotty/tools/dotc/typer Expand file tree Collapse file tree 2 files changed +56
-3
lines changed Original file line number Diff line number Diff line change @@ -2348,7 +2348,7 @@ class Typer extends Namer
2348
2348
def dummyArg (tp : Type ) = untpd.Ident (nme.??? ).withTypeUnchecked(tp)
2349
2349
2350
2350
def addImplicitArgs (implicit ctx : Context ) = {
2351
- def implicitArgs (formals : List [Type ]): List [Tree ] = formals match {
2351
+ def implicitArgs (formals : List [Type ], n : Int ): List [Tree ] = formals match {
2352
2352
case Nil => Nil
2353
2353
case formal :: formals1 =>
2354
2354
val arg = inferImplicitArg(formal, tree.pos.endPos)
@@ -2361,10 +2361,17 @@ class Typer extends Namer
2361
2361
// If there are none, we have to propagate the ambiguity to the caller.
2362
2362
arg :: formals1.map(dummyArg)
2363
2363
case _ =>
2364
- arg :: implicitArgs(formals1)
2364
+ // If the implicit parameter list is dependent we must propagate inferred
2365
+ // types through the remainder of the parameter list similarly to how it's
2366
+ // done for non-implicit parameter lists in Applications#matchArgs#addTyped.
2367
+ val formals2 =
2368
+ if (wtp.isParamDependent && arg.tpe.exists)
2369
+ formals1 mapconserve {f1 => safeSubstParam(f1, wtp.paramRefs(n), arg.tpe)}
2370
+ else formals1
2371
+ arg :: implicitArgs(formals2, n+ 1 )
2365
2372
}
2366
2373
}
2367
- val args = implicitArgs(wtp.paramInfos)
2374
+ val args = implicitArgs(wtp.paramInfos, 0 )
2368
2375
2369
2376
def propagatedFailure (args : List [Tree ]): Type = args match {
2370
2377
case arg :: args1 =>
Original file line number Diff line number Diff line change
1
+ trait Foo [In ] { type Out }
2
+
3
+ object Test {
4
+ implicit def fooInt : Foo [Int ] { type Out = String } = ???
5
+ implicit def str : String = ???
6
+
7
+ def test1 [A ](f1 : Foo [A ])(implicit f2 : f1.Out ) = ???
8
+ def test2 [A ](implicit f1 : Foo [A ], f2 : f1.Out ) = ???
9
+
10
+ test1(fooInt) // OK
11
+ test2 // OK
12
+ }
13
+
14
+ object Test2 {
15
+ implicit def fooInt : Foo [Int ] { type Out = String } = ???
16
+ implicit def fooString : Foo [String ] { type Out = Boolean } = ???
17
+ implicit def fooBoolean : Foo [Boolean ] { type Out = Double } = ???
18
+
19
+ def test3 [A ](f1 : Foo [A ], f2 : Foo [f1.Out ])(implicit f3 : Foo [f2.Out ]): f3.Out = ???
20
+ def test4 [A ](implicit f1 : Foo [A ], f2 : Foo [f1.Out ], f3 : Foo [f2.Out ]): f3.Out = ???
21
+
22
+ val t3 = test3(fooInt, fooString)
23
+ t3 : Double
24
+ val t4 = test4[Int ]
25
+ t4 : Double
26
+ }
27
+
28
+ object Test3 {
29
+ def fooInt : Foo [Int ] { type Out = String } = ???
30
+ implicit def str : String = ???
31
+
32
+ def test5 [A ](implicit f1 : Foo [A ] = fooInt, f2 : f1.Out ) = f2
33
+
34
+ val t5 = test5
35
+ t5 : String
36
+ }
37
+
38
+ object Test4 {
39
+ implicit def fooInt : Foo [Int ] { type Out = String } = ???
40
+ def str : String = ???
41
+
42
+ def test6 [A ](implicit f1 : Foo [A ], f2 : f1.Out = str) = f2
43
+
44
+ val t6 = test6
45
+ t6 : String
46
+ }
You can’t perform that action at this time.
0 commit comments