Skip to content

Commit 0f86044

Browse files
authored
Merge pull request #427 from sjrd/fix-issue-423
Fix #423: Merge the TypeBounds of type members without needing subtyping.
2 parents db863bd + f69ecde commit 0f86044

File tree

1 file changed

+49
-1
lines changed
  • tasty-query/shared/src/main/scala/tastyquery

1 file changed

+49
-1
lines changed

tasty-query/shared/src/main/scala/tastyquery/Types.scala

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ object Types {
198198
ResolveMemberResult.TypeMember(rightSyms, rightBounds)
199199
) =>
200200
val syms = mergeSyms(leftSyms, rightSyms)
201-
val bounds = leftBounds.intersect(rightBounds)
201+
val bounds = mergeTypeMemberTypeBounds(leftBounds, rightBounds)
202202
ResolveMemberResult.TypeMember(syms, bounds)
203203

204204
// Cases that cannot happen -- list them to preserve exhaustivity checking of every other case
@@ -228,6 +228,54 @@ object Types {
228228
case _ =>
229229
throw InvalidProgramStructureException(s"Cannot merge types $tp1 and $tp2")
230230
end mergeTermMemberTypes
231+
232+
private def mergeTypeMemberTypeBounds(bounds1: TypeBounds, bounds2: TypeBounds)(using Context): TypeBounds =
233+
// This implementation assumes that the program structure is valid
234+
(bounds1, bounds2) match
235+
case _ if bounds1 eq bounds2 =>
236+
bounds1
237+
case (bounds1: TypeAlias, _) =>
238+
bounds1
239+
case (_, bounds2: TypeAlias) =>
240+
bounds2
241+
242+
case (bounds1 @ AbstractTypeBounds(low1, high1), bounds2 @ AbstractTypeBounds(low2, high2)) =>
243+
val mergedLow = mergeTypeMemberLowBounds(low1, low2)
244+
val mergedHigh = mergeTypeMemberHighBounds(high1, high2)
245+
bounds1.derivedTypeBounds(mergedLow, mergedHigh)
246+
end mergeTypeMemberTypeBounds
247+
248+
private def mergeTypeMemberLowBounds(low1: Type, low2: Type)(using Context): Type =
249+
(low1.dealias, low2.dealias) match
250+
case (low1: TypeLambda, low2: TypeLambda) if low1.paramNames.sizeCompare(low2.paramNames) == 0 =>
251+
low1.derivedLambdaType(
252+
low1.paramNames,
253+
low1.paramTypeBounds,
254+
mergeTypeMemberLowBounds(low1.resultType, low2.instantiate(low1.paramRefs))
255+
)
256+
case (_: NothingType, _) | (_, _: AnyKindType) =>
257+
low2
258+
case (_, _: NothingType) | (_: AnyKindType, _) =>
259+
low1
260+
case _ =>
261+
low1 | low2
262+
end mergeTypeMemberLowBounds
263+
264+
private def mergeTypeMemberHighBounds(high1: Type, high2: Type)(using Context): Type =
265+
(high1.dealias, high2.dealias) match
266+
case (high1: TypeLambda, high2: TypeLambda) if high1.paramNames.sizeCompare(high2.paramNames) == 0 =>
267+
high1.derivedLambdaType(
268+
high1.paramNames,
269+
high1.paramTypeBounds,
270+
mergeTypeMemberHighBounds(high1.resultType, high2.instantiate(high1.paramRefs))
271+
)
272+
case (_: AnyKindType, _) | (_, _: NothingType) =>
273+
high2
274+
case (_, _: AnyKindType) | (_: NothingType, _) =>
275+
high1
276+
case _ =>
277+
high1 & high2
278+
end mergeTypeMemberHighBounds
231279
end ResolveMemberResult
232280

233281
/** A type parameter of a type constructor.

0 commit comments

Comments
 (0)