@@ -30,8 +30,8 @@ object CheckRealizable {
30
30
class NotFinal (sym : Symbol )(implicit ctx : Context )
31
31
extends Realizability (i " refers to nonfinal $sym" )
32
32
33
- class HasProblemBounds (typ : SingleDenotation )(implicit ctx : Context )
34
- extends Realizability (i " has a member $typ with possibly conflicting bounds ${typ. info.bounds.lo} <: ... <: ${typ. info.bounds.hi}" )
33
+ class HasProblemBounds (name : Name , info : Type )(implicit ctx : Context )
34
+ extends Realizability (i " has a member $name with possibly conflicting bounds ${info.bounds.lo} <: ... <: ${info.bounds.hi}" )
35
35
36
36
class HasProblemBaseArg (typ : Type , argBounds : TypeBounds )(implicit ctx : Context )
37
37
extends Realizability (i " has a base type $typ with possibly conflicting parameter bounds ${argBounds.lo} <: ... <: ${argBounds.hi}" )
@@ -96,6 +96,14 @@ class CheckRealizable(implicit ctx: Context) {
96
96
else boundsRealizability(tp).andAlso(memberRealizability(tp))
97
97
}
98
98
99
+ private def refinedNames (tp : Type ): Set [Name ] = tp.dealias match {
100
+ case tp : RefinedType => refinedNames(tp.parent) + tp.refinedName
101
+ case tp : AndType => refinedNames(tp.tp1) ++ refinedNames(tp.tp2)
102
+ case tp : OrType => refinedNames(tp.tp1) ++ refinedNames(tp.tp2)
103
+ case tp : TypeProxy => refinedNames(tp.underlying)
104
+ case _ => Set .empty
105
+ }
106
+
99
107
/** `Realizable` if `tp` has good bounds, a `HasProblem...` instance
100
108
* pointing to a bad bounds member otherwise. "Has good bounds" means:
101
109
*
@@ -107,12 +115,21 @@ class CheckRealizable(implicit ctx: Context) {
107
115
* also lead to base types with bad bounds).
108
116
*/
109
117
private def boundsRealizability (tp : Type ) = {
110
- val mbrProblems =
118
+
119
+ val memberProblems =
111
120
for {
112
121
mbr <- tp.nonClassTypeMembers
113
122
if ! (mbr.info.loBound <:< mbr.info.hiBound)
114
123
}
115
- yield new HasProblemBounds (mbr)
124
+ yield new HasProblemBounds (mbr.name, mbr.info)
125
+
126
+ val refinementProblems =
127
+ for {
128
+ name <- refinedNames(tp)
129
+ mbr <- tp.member(name).alternatives
130
+ if ! (mbr.info.loBound <:< mbr.info.hiBound)
131
+ }
132
+ yield new HasProblemBounds (name, mbr.info)
116
133
117
134
def baseTypeProblems (base : Type ) = base match {
118
135
case AndType (base1, base2) =>
@@ -126,12 +143,13 @@ class CheckRealizable(implicit ctx: Context) {
126
143
val baseProblems =
127
144
tp.baseClasses.map(_.baseTypeOf(tp)).flatMap(baseTypeProblems)
128
145
129
- (((Realizable : Realizability )
130
- /: mbrProblems)(_ andAlso _)
146
+ ((((Realizable : Realizability )
147
+ /: memberProblems)(_ andAlso _)
148
+ /: refinementProblems)(_ andAlso _)
131
149
/: baseProblems)(_ andAlso _)
132
150
}
133
151
134
- /** `Realizable` if all of `tp`'s non-struct fields have realizable types,
152
+ /** `Realizable` if all of `tp`'s non-strict fields have realizable types,
135
153
* a `HasProblemField` instance pointing to a bad field otherwise.
136
154
*/
137
155
private def memberRealizability (tp : Type ) = {
0 commit comments