Skip to content

Commit a7622b2

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 4873728 commit a7622b2

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
@@ -1470,17 +1470,21 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
14701470
/** Is `alt` a method or polytype whose result type after the first value parameter
14711471
* section conforms to the expected type `resultType`? If `resultType`
14721472
* is a `IgnoredProto`, pick the underlying type instead.
1473+
* If `alt`does not have method or poly type, and `followApply` is true, consider
1474+
* all apply members instead. In all other cases return `true`.
14731475
*/
1474-
def resultConforms(altSym: Symbol, altType: Type, resultType: Type)(implicit ctx: Context): Boolean =
1475-
resultType.revealIgnored match {
1476+
def resultConforms(altSym: Symbol, altType: Type, resultType: Type)(implicit ctx: Context): Boolean = {
1477+
def recur(altType: Type, followApply: Boolean): Boolean = resultType.revealIgnored match {
14761478
case resultType: ValueType =>
14771479
altType.widen match {
1478-
case tp: PolyType => resultConforms(altSym, constrained(tp).resultType, resultType)
1480+
case tp: PolyType => recur(constrained(tp).resultType, followApply)
14791481
case tp: MethodType => constrainResult(altSym, tp.resultType, resultType)
1480-
case _ => true
1482+
case _ => !followApply || onMethod(altType, followApply)(recur(_, followApply = false))
14811483
}
14821484
case _ => true
14831485
}
1486+
recur(altType, followApply = true)
1487+
}
14841488

14851489
/** If the `chosen` alternative has a result type incompatible with the expected result
14861490
* 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)