Permalink
Browse files

Downwards comparisons for implicit search and overloading resolution

Compare selected contravariant arguments as if they were covariant.
Which ones is explained in the doc comment for method `isAsSpecificValueType`
in Applications.scala.

This has the same motivation than what @paulp proposed around 2012. The solution is a bit
different from the one proposed then because it only affects top-level parameters.
  • Loading branch information...
odersky committed May 4, 2016
1 parent 039e20f commit 89540268e6c49fb92b9ca61249e46bb59981bf5a
@@ -81,5 +81,8 @@ object Mode {
/** We are currently unpickling Scala2 info */
val Scala2Unpickling = newMode(13, "Scala2Unpickling")
/** Use Scala2 scheme for overloading and implicit resolution */
val OldOverloadingResolution = newMode(14, "OldOverloadingResolution")
val PatternOrType = Pattern | Type
}
@@ -915,13 +915,54 @@ trait Applications extends Compatibility { self: Typer =>
{
implicit val ctx: Context = nestedCtx
isCompatible(tp1, constrained(tp2).resultType)
isAsSpecificValueType(tp1, constrained(tp2).resultType)
}
case _ => // (3b)
isCompatible(tp1, tp2)
isAsSpecificValueType(tp1, tp2)
}
}}
/** Test whether value type `tp1` is as specific as value type `tp2`.
* Let's abbreviate this to `tp1 <:s tp2`.
* Previously, `<:s` was the same as `<:`. This behavior is still
* available under mode `Mode.OldOverloadingResolution`. The new behavior
* is different, however. Here, `T <:s U` iff
*
* flip(T) <: flip(U)
*
* where `flip` changes top-level contravariant type aliases to covariant ones.
* Intuitively `<:s` means subtyping `<:`, except that all top-level arguments
* to contravariant parameters are compared as if they were covariant. E.g. given class
*
* class Cmp[-X]
*
* `Cmp[T] <:s Cmp[U]` if `T <: U`. On the other hand, nested occurrences
* of parameters are not affected.
* So `T <: U` would imply `List[Cmp[U]] <:s List[Cmp[T]]`, as usual.
*
* This relation might seem strange, but it models closely what happens for methods.
* Indeed, if we integrate the existing rules for methods into `<:s` we have now that
*
* (T1)T2 <:s (U1)U2
*
* iff
*
* T1 => T2 <:s U1 => U2
*/
def isAsSpecificValueType(tp1: Type, tp2: Type)(implicit ctx: Context) =
if (ctx.mode.is(Mode.OldOverloadingResolution))
isCompatible(tp1, tp2)
else {
val flip = new TypeMap {
def apply(t: Type) = t match {
case t: TypeAlias if variance > 0 && t.variance < 0 => t.derivedTypeAlias(t.alias, 1)
case t: TypeBounds => t
case _ => mapOver(t)
}
}
isCompatible(flip(tp1), flip(tp2))
}
/** Drop any implicit parameter section */
def stripImplicit(tp: Type): Type = tp match {
case mt: ImplicitMethodType if !mt.isDependent =>
@@ -439,7 +439,19 @@ trait Implicits { self: Typer =>
result
case result: AmbiguousImplicits =>
val deepPt = pt.deepenProto
if (deepPt ne pt) inferImplicit(deepPt, argument, pos) else result
if (deepPt ne pt) inferImplicit(deepPt, argument, pos)
else if (ctx.scala2Mode && !ctx.mode.is(Mode.OldOverloadingResolution)) {
inferImplicit(pt, argument, pos)(ctx.addMode(Mode.OldOverloadingResolution)) match {
case altResult: SearchSuccess =>
ctx.migrationWarning(
s"According to new implicit resolution rules, this will be ambiguous:\n ${result.explanation}",
pos)
altResult
case _ =>
result
}
}
else result
case _ =>
assert(prevConstr eq ctx.typerState.constraint)
result
@@ -119,8 +119,8 @@ class tests extends CompilerTest {
@Test def neg_typedIdents() = compileDir(negDir, "typedIdents")
val negCustomArgs = negDir + "customArgs/"
@Test def neg_typers = compileFile(negCustomArgs, "typers")(allowDoubleBindings)
@Test def neg_overrideClass = compileFile(negCustomArgs, "overrideClass", List("-language:Scala2"))
@Test def neg_typers() = compileFile(negCustomArgs, "typers")(allowDoubleBindings)
@Test def neg_overrideClass = compileFile(negCustomArgs, "overrideClass", scala2mode)
@Test def neg_autoTupling = compileFile(negCustomArgs, "autoTuplingTest", args = "-language:noAutoTupling" :: Nil)
@Test def neg_i1050 = compileFile(negCustomArgs, "i1050", List("-strict"))
@Test def neg_i1240 = compileFile(negCustomArgs, "i1240")(allowDoubleBindings)
File renamed without changes.

0 comments on commit 8954026

Please sign in to comment.