Skip to content

Commit

Permalink
A slightly more conservative version of #14128
Browse files Browse the repository at this point in the history
Two changes

 - Fix `hasUpperBound` to work correctly for higher-kinded types
 - A more conservative fix in `IsFullyDefinedAccumulator`. We now maintain
   the symmetry that

     - if variance < 0, we maximize
     - if variance > 0 (and Nothing is admissible) we minimize
     - only if variance = 0, we use the upper bound as a tie breaker

   Previously, we maximized even if variance > 0 if there was an upper but
   no lower bound. But that was asymmetric since there is no corresponding
   case where we minimize at variance < 0 if there is a lower but no upper
   bound.
  • Loading branch information
odersky committed Aug 7, 2023
1 parent d0b2151 commit 0faa252
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 2 deletions.
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@ object Types {
case _ => false
}

/** Is this type exactly `Any`, or a type lambda ending in `Any`? */
def isTopOfSomeKind(using Context): Boolean = dealias match
case tp: TypeLambda => tp.resType.isTopOfSomeKind
case _ => isExactlyAny

def isBottomType(using Context): Boolean =
if ctx.mode.is(Mode.SafeNulls) && !ctx.phase.erasedTypes then hasClassSymbol(defn.NothingClass)
else isBottomTypeAfterErasure
Expand Down Expand Up @@ -4896,7 +4901,7 @@ object Types {
def hasLowerBound(using Context): Boolean = !currentEntry.loBound.isExactlyNothing

/** For uninstantiated type variables: Is the upper bound different from Any? */
def hasUpperBound(using Context): Boolean = !currentEntry.hiBound.finalResultType.isExactlyAny
def hasUpperBound(using Context): Boolean = !currentEntry.hiBound.isTopOfSomeKind

/** Unwrap to instance (if instantiated) or origin (if not), until result
* is no longer a TypeVar
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Inferencing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,11 @@ object Inferencing {
// else hold off instantiating unbounded unconstrained variable
else if direction != 0 then
instantiate(tvar, fromBelow = direction < 0)
else if variance >= 0 && (force.ifBottom == IfBottom.ok && !tvar.hasUpperBound || tvar.hasLowerBound) then
else if variance >= 0 && tvar.hasLowerBound then
instantiate(tvar, fromBelow = true)
else if (variance > 0 || variance == 0 && !tvar.hasUpperBound)
&& force.ifBottom == IfBottom.ok
then // if variance == 0, prefer upper bound if one is given
instantiate(tvar, fromBelow = true)
else if variance >= 0 && force.ifBottom == IfBottom.fail then
fail = true
Expand Down

0 comments on commit 0faa252

Please sign in to comment.