@@ -30,8 +30,8 @@ object CheckRealizable {
3030 class NotFinal (sym : Symbol )(implicit ctx : Context )
3131 extends Realizability (i " refers to nonfinal $sym" )
3232
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}" )
3535
3636 class HasProblemBaseArg (typ : Type , argBounds : TypeBounds )(implicit ctx : Context )
3737 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) {
9696 else boundsRealizability(tp).andAlso(memberRealizability(tp))
9797 }
9898
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+
99107 /** `Realizable` if `tp` has good bounds, a `HasProblem...` instance
100108 * pointing to a bad bounds member otherwise. "Has good bounds" means:
101109 *
@@ -107,12 +115,21 @@ class CheckRealizable(implicit ctx: Context) {
107115 * also lead to base types with bad bounds).
108116 */
109117 private def boundsRealizability (tp : Type ) = {
110- val mbrProblems =
118+
119+ val memberProblems =
111120 for {
112121 mbr <- tp.nonClassTypeMembers
113122 if ! (mbr.info.loBound <:< mbr.info.hiBound)
114123 }
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)
116133
117134 def baseTypeProblems (base : Type ) = base match {
118135 case AndType (base1, base2) =>
@@ -126,12 +143,13 @@ class CheckRealizable(implicit ctx: Context) {
126143 val baseProblems =
127144 tp.baseClasses.map(_.baseTypeOf(tp)).flatMap(baseTypeProblems)
128145
129- (((Realizable : Realizability )
130- /: mbrProblems)(_ andAlso _)
146+ ((((Realizable : Realizability )
147+ /: memberProblems)(_ andAlso _)
148+ /: refinementProblems)(_ andAlso _)
131149 /: baseProblems)(_ andAlso _)
132150 }
133151
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,
135153 * a `HasProblemField` instance pointing to a bad field otherwise.
136154 */
137155 private def memberRealizability (tp : Type ) = {
0 commit comments