-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathi16018c.scala
More file actions
68 lines (60 loc) · 3.16 KB
/
i16018c.scala
File metadata and controls
68 lines (60 loc) · 3.16 KB
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Negative half of the directional matrix for the fix to
// `TypeComparer.compareCaptured` (#16018 / Existential widening for wildcard
// arguments).
//
// These shapes must remain *rejected* after the fix: the fix only adds
// widening that is justified by variance — covariant + upper bound,
// contravariant + lower bound. Any other combination is unsound and must
// keep the same diagnostic it had before. If any of these `//<space>error`
// markers stops firing, the fix has overreached.
object Test:
class Co[+T]
class Contra[-T]
class Inv[T]
// ---- A. Invariant containers never widen the wildcard ---------------
def inv_upper_bad[M](xs: Inv[? <: M]): Inv[M] = xs // error
def inv_lower_bad[M](xs: Inv[? >: M]): Inv[M] = xs // error
// ---- B. Covariant with a *lower*-bounded wildcard does not widen ----
//
// For covariant F, `F[? >: lo]` is the type of F[X] for some X >: lo.
// That has no useful relationship to F[lo] — picking X = Any is
// permitted yet gives F[Any], not F[lo].
def co_lower_bad[M](xs: Co[? >: M]): Co[M] = xs // error
// ---- C. Contravariant with an *upper*-bounded wildcard does not widen
//
// Dual to (B): for contravariant G, `G[? <: hi]` makes no commitment
// that the picked X is `hi` itself; it could be `Nothing`.
def contra_upper_bad[M](xs: Contra[? <: M]): Contra[M] = xs // error
// ---- D. The required type's hi is strictly tighter than the wildcard
//
// `Co[? <: Any]` is the trivial widening shape (any T). It must not be
// accepted at `Co[Holder]` because the wildcard's hi (`Any`) is wider
// than the target.
trait Holder
def co_too_wide(xs: Co[? <: Any]): Co[Holder] = xs // error
// ---- E. Upper-boundary check, covariant ------------------------------
//
// Boundary companion to `soundness_guard_co` in tests/pos/i16018c.scala.
// For `CoBounded[+T <: Holder]` fed `CoBounded[? <: Any]`, the effective
// wildcard hi computed by the fix is `Any & Holder = Holder`. The
// *positive* counterpart pins conformance at `CoBounded[Holder]`
// (admits THE FIX, rejects NAIVE). This negative pins that conformance
// stops there: `CoBounded[Sub]` for `Sub <: Holder` must still be
// rejected. Note that all three of OLD / NAIVE / THE FIX reject this
// case (each computes a different LHS but each LHS is ⊄ Sub), so this
// case is a *boundary* test, not a distinguishing one — read the pos
// counterpart for the implementation-distinguishing check.
class Sub extends Holder
class CoBounded[+T <: Holder]
def co_guard_upper_boundary(xs: CoBounded[? <: Any]): CoBounded[Sub] = xs // error
// ---- F. Lower-boundary check, contravariant --------------------------
//
// Dual to (E). The positive counterpart `soundness_guard_contra` pins
// conformance at `ContraBounded[Holder]`. This negative pins that a
// *strict supertype* of `Holder` is not reached (variance flips the
// direction). Same caveat as (E): all three implementations reject,
// so this is a boundary check.
class Super
class HolderS extends Super
class ContraBounded[-T >: HolderS]
def contra_guard_lower_boundary(xs: ContraBounded[? >: Nothing]): ContraBounded[Super] = xs // error