Downwards comparisons for implicit search and overloading resolution · scala/scala3@340f883 (original) (raw)
`@@ -915,13 +915,54 @@ trait Applications extends Compatibility { self: Typer =>
`
915
915
``
916
916
` {
`
917
917
`implicit val ctx: Context = nestedCtx
`
918
``
`-
isCompatible(tp1, constrained(tp2).resultType)
`
``
918
`+
isAsSpecificValueType(tp1, constrained(tp2).resultType)
`
919
919
` }
`
920
920
`case _ => // (3b)
`
921
``
`-
isCompatible(tp1, tp2)
`
``
921
`+
isAsSpecificValueType(tp1, tp2)
`
922
922
` }
`
923
923
` }}
`
924
924
``
``
925
`` +
/** Test whether value type tp1
is as specific as value type tp2
.
``
``
926
`` +
- Let's abbreviate this to
tp1 <:s tp2
.
``
``
927
`` +
- Previously,
<:s
was the same as<:
. This behavior is still
``
``
928
`` +
- available under mode
Mode.OldOverloadingResolution
. The new behavior
``
``
929
`` +
- is different, however. Here,
T <:s U
iff
``
``
930
`+
`
``
931
`+
- flip(T) <: flip(U)
`
``
932
`+
`
``
933
`` +
- where
flip
changes top-level contravariant type aliases to covariant ones.
``
``
934
`` +
- Intuitively
<:s
means subtyping<:
, except that all top-level arguments
``
``
935
`+
- to contravariant parameters are compared as if they were covariant. E.g. given class
`
``
936
`+
`
``
937
`+
- class Cmp[-X]
`
``
938
`+
`
``
939
`` +
Cmp[T] <:s Cmp[U]
ifT <: U
. On the other hand, nested occurrences
``
``
940
`+
- of parameters are not affected.
`
``
941
`` +
- So
T <: U
would implyList[Cmp[U]] <:s List[Cmp[T]]
, as usual.
``
``
942
`+
`
``
943
`+
- This relation might seem strange, but it models closely what happens for methods.
`
``
944
`` +
- Indeed, if we integrate the existing rules for methods into
<:s
we have now that
``
``
945
`+
`
``
946
`+
- (T1)T2 <:s (U1)U2
`
``
947
`+
`
``
948
`+
- iff
`
``
949
`+
`
``
950
`+
- T1 => T2 <:s U1 => U2
`
``
951
`+
*/
`
``
952
`+
def isAsSpecificValueType(tp1: Type, tp2: Type)(implicit ctx: Context) =
`
``
953
`+
if (ctx.mode.is(Mode.OldOverloadingResolution))
`
``
954
`+
isCompatible(tp1, tp2)
`
``
955
`+
else {
`
``
956
`+
val flip = new TypeMap {
`
``
957
`+
def apply(t: Type) = t match {
`
``
958
`+
case t: TypeAlias if variance > 0 && t.variance < 0 => t.derivedTypeAlias(t.alias, 1)
`
``
959
`+
case t: TypeBounds => t
`
``
960
`+
case _ => mapOver(t)
`
``
961
`+
}
`
``
962
`+
}
`
``
963
`+
isCompatible(flip(tp1), flip(tp2))
`
``
964
`+
}
`
``
965
+
925
966
`/** Drop any implicit parameter section */
`
926
967
`def stripImplicit(tp: Type): Type = tp match {
`
927
968
`case mt: ImplicitMethodType if !mt.isDependent =>
`