@@ -155,95 +155,53 @@ final class ProperGadtConstraint private(
155
155
* In `subsumes`, we have to recognize the fact that both T(param)$1 and T(param)$2
156
156
* represents the same path-dependent type, to give the correct result.
157
157
*/
158
- def subsumes (left : GadtConstraint , right : GadtConstraint , pre : GadtConstraint )(using Context ): Boolean = {
159
- def checkSubsumes (c1 : Constraint , c2 : Constraint , pre : Constraint ): Boolean = {
160
- if (c2 eq pre) true
161
- else if (c1 eq pre) false
162
- else {
163
- val saved = constraint
164
-
165
- def computeNewParams =
166
- val params1 = c1.domainParams.toSet
167
- val params2 = c2.domainParams.toSet
168
- val preParams = pre.domainParams.toSet
169
- /** Type parameter registered after branching */
170
- (params1.diff(preParams), params2.diff(preParams))
171
-
172
- val (newParams1, newParams2) = computeNewParams
173
-
174
- // When new types are registered after pre, for left to subsume right, it should contain all types
175
- // newly registered in right.
176
- def checkNewParams : Boolean = (left, right) match {
177
- case (left : ProperGadtConstraint , right : ProperGadtConstraint ) =>
178
- newParams2 forall { p2 =>
179
- val tp2 = right.externalize(p2)
180
- left.tvarOf(tp2) != null
158
+ def subsumes (left : GadtConstraint , right : GadtConstraint , pre : GadtConstraint )(using Context ): Boolean =
159
+ def checkSubsumes (left : ProperGadtConstraint , right : ProperGadtConstraint , pre : ProperGadtConstraint ): Boolean = {
160
+ def rightToLeft : TypeParamRef => TypeParamRef = {
161
+ val preParams = pre.constraint.domainParams.toSet
162
+ val mapping = {
163
+ var res : SimpleIdentityMap [TypeParamRef , TypeParamRef ] = SimpleIdentityMap .empty
164
+
165
+ right.constraint.domainParams.foreach { p2 =>
166
+ left.tvarOf(right.externalize(p2)) match {
167
+ case null =>
168
+ case tv : TypeVar =>
169
+ res = res.updated(p2, tv.origin)
181
170
}
182
- case _ => true
183
- }
184
-
185
- checkNewParams && {
186
- // Computes mappings between the newly-registered type params in
187
- // the two branches.
188
- def createMappings = {
189
- var mapping1 : SimpleIdentityMap [TypeParamRef , TypeParamRef ] = SimpleIdentityMap .empty
190
- var mapping2 : SimpleIdentityMap [TypeParamRef , TypeParamRef ] = SimpleIdentityMap .empty
191
-
192
- (left, right) match {
193
- case (left : ProperGadtConstraint , right : ProperGadtConstraint ) =>
194
- newParams1 foreach { p1 =>
195
- val tp1 = left.externalize(p1)
196
- right.tvarOf(tp1) match {
197
- case null =>
198
- case tvar2 : TypeVar =>
199
- mapping1 = mapping1.updated(p1, tvar2.origin)
200
- mapping2 = mapping2.updated(tvar2.origin, p1)
201
- }
202
- }
203
- case _ =>
204
- }
205
-
206
- def mapTypeParam (m : SimpleIdentityMap [TypeParamRef , TypeParamRef ])(tpr : TypeParamRef ) =
207
- m(tpr) match
208
- case null => tpr
209
- case tpr1 : TypeParamRef => tpr1
210
-
211
- (mapTypeParam(mapping1), mapTypeParam(mapping2))
212
171
}
213
172
214
- // Bridge between the newly-registered types in c2 and c1
215
- val (mapping1, mapping2) = createMappings
173
+ res
174
+ }
216
175
217
- try {
218
- // checks existing type parameters in `pre`
219
- def existing : Boolean = pre.forallParams { p =>
220
- c1.contains(p) &&
221
- c2.upper(p).forall { q =>
222
- c1.isLess(p, mapping1(q))
223
- } && isSubTypeWhenFrozen(c1.nonParamBounds(p), c2.nonParamBounds(p))
224
- }
176
+ def func (p2 : TypeParamRef ) =
177
+ if pre.constraint.domainParams contains p2 then p2
178
+ else mapping(p2)
225
179
226
- // checks new type parameters in `c1`
227
- def added : Boolean = newParams1 forall { p1 =>
228
- val p2 = mapping1(p1)
229
- c2.upper(p2).forall { q =>
230
- c1.isLess(p1, mapping2(q))
231
- } && isSubTypeWhenFrozen(c1.nonParamBounds(p1), c2.nonParamBounds(p2))
232
- }
180
+ func
181
+ }
233
182
234
- existing && checkNewParams && added
235
- } finally constraint = saved
183
+ def checkParam (p2 : TypeParamRef ) =
184
+ rightToLeft(p2).match {
185
+ case null => false
186
+ case p1 : TypeParamRef =>
187
+ left.constraint.entry(p1).exists
188
+ && right.constraint.upper(p1).map(rightToLeft).forall(left.constraint.isLess(p1, _))
189
+ && isSubTypeWhenFrozen(left.constraint.nonParamBounds(p1), right.constraint.nonParamBounds(p2))
236
190
}
237
- }
238
- }
239
191
240
- def extractConstraint (g : GadtConstraint ) = g match {
241
- case s : ProperGadtConstraint => s.constraint
242
- case EmptyGadtConstraint => OrderingConstraint .empty
192
+ def todos : Set [TypeParamRef ] =
193
+ right.constraint.domainParams.toSet ++ pre.constraint.domainParams
194
+
195
+ todos.forall(checkParam)
243
196
}
244
197
245
- checkSubsumes(extractConstraint(left), extractConstraint(right), extractConstraint(pre))
246
- }
198
+ (left, right, pre) match {
199
+ case (left : ProperGadtConstraint , right : ProperGadtConstraint , pre : ProperGadtConstraint ) =>
200
+ checkSubsumes(left, right, pre)
201
+ case (_, EmptyGadtConstraint , _) => true
202
+ case (EmptyGadtConstraint , _, _) => false
203
+ case (_, _, EmptyGadtConstraint ) => false
204
+ }
247
205
248
206
override protected def legalBound (param : TypeParamRef , rawBound : Type , isUpper : Boolean )(using Context ): Type =
249
207
// GADT constraints never involve wildcards and are not propagated outside
0 commit comments