blob: 67ef7fcc69691ead2e5d8bb5fae3acf3c2d34d77 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
import language.higherKinds
trait T {
def t = 0
}
trait Foo {
def coflatMap[A <: T](f: A): A
}
object O extends Foo {
def coflatMap[A <: T](f: A) = {
val f2 = coflatMap(f) // inferred in 2.9.2 / 2.10.0 as [Nothing]
f2.t // so this does't type check.
f2
}
}
// Why? When a return type is inherited, the derived method
// symbol first gets a preliminary type assigned, based on the
// 1) method type of a unique matching super member
// 2) viewed as a member type of the inheritor (to substitute,
// e.g. class type parameters)
// 3) substituted to replace the super-method's type parameters
// with those of the inheritor
// 4) dissected to take just the return type wrapped in thisMethodType().
//
// In Scala 2.10.0 and earlier, this preliminary method type
//
// 1) [A#11329 <: <empty>#3.this.T#7068](<param> f#11333: A#11329)A#11329
// 2) [A#11329 <: <empty>#3.this.T#7068](<param> f#11333: A#11329)A#11329
// 3) (<param> f#12556: A#11336)A#11336
// 4) [A#11336 <: <empty>#3.this.T#7068](<param> f#12552: A#11337&0)A#11336
//
// The type #4 from the old version is problematic: the parameter is typed with
// a skolem for the type parameter `A`. It won't be considered to match the
// method it overrides, instead they are seen as being overloaded, and type inference
// goes awry (Nothing is inferred as the type argument for the recursive call
// to coflatMap.
//
// The Namers patch adds one step here: it subsitutes the type parameter symbols
// for the skolems:
//
// https://github.com/scala/scala/commit/b74c33eb#L2R1014
//
// So we end up with a method symbol info:
//
// 5) [A#11336 <: <empty>#3.this.T#7068](<param> f#12505: A#11336)A#11336
//
// This *does* match the method in the super class, and type inference
// chooses the correct type argument.
|