Skip to content

Commit 8284252

Browse files
committed
Consider apply members in constrainResult
So, now we were mis-approximating in the other direction by letting non-methodic alternatives always pass through the resultConforms check. This would let members with apply methods pass where they should not. The problem was previously hidden since members with apply methods tended to be already filtered out in the isApplicable check.
1 parent 23089ad commit 8284252

File tree

3 files changed

+62
-57
lines changed

3 files changed

+62
-57
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,17 +1472,21 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
14721472
/** Is `alt` a method or polytype whose result type after the first value parameter
14731473
* section conforms to the expected type `resultType`? If `resultType`
14741474
* is a `IgnoredProto`, pick the underlying type instead.
1475+
* If `alt`does not have method or poly type, and `followApply` is true, consider
1476+
* all apply members instead. In all other cases return `true`.
14751477
*/
1476-
def resultConforms(altSym: Symbol, altType: Type, resultType: Type)(implicit ctx: Context): Boolean =
1477-
resultType.revealIgnored match {
1478+
def resultConforms(altSym: Symbol, altType: Type, resultType: Type)(implicit ctx: Context): Boolean = {
1479+
def recur(altType: Type, followApply: Boolean): Boolean = resultType.revealIgnored match {
14781480
case resultType: ValueType =>
14791481
altType.widen match {
1480-
case tp: PolyType => resultConforms(altSym, constrained(tp).resultType, resultType)
1482+
case tp: PolyType => recur(constrained(tp).resultType, followApply)
14811483
case tp: MethodType => constrainResult(altSym, tp.resultType, resultType)
1482-
case _ => true
1484+
case _ => !followApply || onMethod(altType, followApply)(recur(_, followApply = false))
14831485
}
14841486
case _ => true
14851487
}
1488+
recur(altType, followApply = true)
1489+
}
14861490

14871491
/** If the `chosen` alternative has a result type incompatible with the expected result
14881492
* type `pt`, run overloading resolution again on all alternatives that do match `pt`.

tests/neg/i6450.scala

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,55 +13,3 @@ object Test {
1313
val f: Foo123 = f(1) // error: Not found: type Foo123
1414

1515
}
16-
17-
object Test2 {
18-
trait A {
19-
def apply(x: AnyRef): Int
20-
}
21-
object B {
22-
def f(e: Any): A = ???
23-
val f: A = f(null)
24-
}
25-
}
26-
27-
object Test3 {
28-
trait A {
29-
def apply(x: String): Int
30-
}
31-
object B {
32-
def f(e: CharSequence): A = ???
33-
val f: A = f(null)
34-
}
35-
}
36-
37-
38-
object Test4 {
39-
trait A {
40-
def apply(x: Any): Int
41-
}
42-
object B {
43-
def f(e: Any): A = ???
44-
val f: A = f(null)
45-
}
46-
}
47-
48-
object Test5 {
49-
trait A {
50-
def apply(x: Any): Int
51-
}
52-
object B {
53-
def f(e: AnyRef): A = ???
54-
val f: A = f(null)
55-
}
56-
}
57-
58-
59-
object Test6 {
60-
trait A {
61-
def apply(x: CharSequence): Int
62-
}
63-
object B {
64-
def f(e: String): A = ???
65-
val f: A = f(null)
66-
}
67-
}

tests/pos/i6450.scala

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ object Test {
2525
val z1: Int = z
2626
}
2727

28-
object Test2 {
28+
object Test1 {
2929

3030
trait A {
3131
def apply(x: Any): Int = 1
@@ -35,4 +35,57 @@ object Test2 {
3535
def f(x: Any): A = new A {}
3636
lazy val f: A = f(null)
3737
}
38+
}
39+
40+
object Test2 {
41+
trait A {
42+
def apply(x: AnyRef): Int
43+
}
44+
object B {
45+
def f(e: Any): A = ???
46+
val f: A = ???
47+
val g: A = f(null)
48+
}
49+
}
50+
51+
object Test3 {
52+
trait A {
53+
def apply(x: String): Int
54+
}
55+
object B {
56+
def f(e: CharSequence): A = ???
57+
val f: A = f(null)
58+
}
59+
}
60+
61+
62+
object Test4 {
63+
trait A {
64+
def apply(x: Any): Int
65+
}
66+
object B {
67+
def f(e: Any): A = ???
68+
val f: A = f(null)
69+
}
70+
}
71+
72+
object Test5 {
73+
trait A {
74+
def apply(x: Any): Int
75+
}
76+
object B {
77+
def f(e: AnyRef): A = ???
78+
val f: A = f(null)
79+
}
80+
}
81+
82+
83+
object Test6 {
84+
trait A {
85+
def apply(x: CharSequence): Int
86+
}
87+
object B {
88+
def f(e: String): A = ???
89+
val f: A = f(null)
90+
}
3891
}

0 commit comments

Comments
 (0)