Skip to content

Commit f833baa

Browse files
authored
Merge pull request #8082 from dotty-staging/change-lambda-variance
Rework variances of higher-kinded types
2 parents 23affe1 + 2396fe9 commit f833baa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+653
-486
lines changed

compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ object DesugarEnums {
4949
val tparams = enumClass.typeParams
5050
def isGround(tp: Type) = tp.subst(tparams, tparams.map(_ => NoType)) eq tp
5151
val targs = tparams map { tparam =>
52-
if (tparam.variance > 0 && isGround(tparam.info.bounds.lo))
52+
if (tparam.is(Covariant) && isGround(tparam.info.bounds.lo))
5353
tparam.info.bounds.lo
54-
else if (tparam.variance < 0 && isGround(tparam.info.bounds.hi))
54+
else if (tparam.is(Contravariant) && isGround(tparam.info.bounds.hi))
5555
tparam.info.bounds.hi
5656
else {
5757
def problem =
58-
if (tparam.variance == 0) "is non variant"
58+
if (!tparam.isOneOf(VarianceFlags)) "is non variant"
5959
else "has bounds that depend on a type parameter in the same parameter list"
6060
errorType(i"""cannot determine type argument for enum parent $enumClass,
6161
|type parameter $tparam $problem""", ctx.source.atSpan(span))

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,9 @@ trait ConstraintHandling[AbstractContext] {
379379
case bounds: TypeBounds =>
380380
val lower = constraint.lower(param)
381381
val upper = constraint.upper(param)
382-
if (lower.nonEmpty && !bounds.lo.isRef(defn.NothingClass) ||
383-
upper.nonEmpty && !bounds.hi.isRef(defn.AnyClass)) constr_println(i"INIT*** $tl")
382+
if lower.nonEmpty && !bounds.lo.isRef(defn.NothingClass)
383+
|| upper.nonEmpty && !bounds.hi.isAny
384+
then constr_println(i"INIT*** $tl")
384385
lower.forall(addOneBound(_, bounds.hi, isUpper = true)) &&
385386
upper.forall(addOneBound(_, bounds.lo, isUpper = false))
386387
case _ =>

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ class Definitions {
535535
@tu lazy val StringModule: Symbol = StringClass.linkedClass
536536
@tu lazy val String_+ : TermSymbol = enterMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final)
537537
@tu lazy val String_valueOf_Object: Symbol = StringModule.info.member(nme.valueOf).suchThat(_.info.firstParamTypes match {
538-
case List(pt) => pt.isRef(AnyClass) || pt.isRef(ObjectClass)
538+
case List(pt) => pt.isAny || pt.isAnyRef
539539
case _ => false
540540
}).symbol
541541

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ object Denotations {
775775

776776
def matchesImportBound(bound: Type)(implicit ctx: Context): Boolean =
777777
if bound.isRef(defn.NothingClass) then false
778-
else if bound.isRef(defn.AnyClass) then true
778+
else if bound.isAny then true
779779
else NoViewsAllowed.normalizedCompatible(info, bound, keepConstraint = false)
780780

781781
// ------ Transformations -----------------------------------------

compiler/src/dotty/tools/dotc/core/GadtConstraint.scala

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -155,26 +155,8 @@ final class ProperGadtConstraint private(
155155
else if (isUpper) addLess(symTvar.origin, boundTvar.origin)
156156
else addLess(boundTvar.origin, symTvar.origin)
157157
case bound =>
158-
val oldUpperBound = bounds(symTvar.origin)
159-
// If we have bounds:
160-
// F >: [t] => List[t] <: [t] => Any
161-
// and we want to record that:
162-
// F <: [+A] => List[A]
163-
// we need to adapt the variance and instead record that:
164-
// F <: [A] => List[A]
165-
// We cannot record the original bound, since it is false that:
166-
// [t] => List[t] <: [+A] => List[A]
167-
//
168-
// Note that the following code is accepted:
169-
// class Foo[F[t] >: List[t]]
170-
// type T = Foo[List]
171-
// precisely because Foo[List] is desugared to Foo[[A] => List[A]].
172-
//
173-
// Ideally we'd adapt the bound in ConstraintHandling#addOneBound,
174-
// but doing it there actually interferes with type inference.
175-
val bound1 = bound.adaptHkVariances(oldUpperBound)
176-
if (isUpper) addUpperBound(symTvar.origin, bound1)
177-
else addLowerBound(symTvar.origin, bound1)
158+
if (isUpper) addUpperBound(symTvar.origin, bound)
159+
else addLowerBound(symTvar.origin, bound)
178160
}
179161
).reporting({
180162
val descr = if (isUpper) "upper" else "lower"

compiler/src/dotty/tools/dotc/core/Hashable.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import scala.util.hashing.{ MurmurHash3 => hashing }
66
import annotation.tailrec
77

88
object Hashable {
9-
9+
1010
/** A null terminated list of BindingTypes. We use `null` here for efficiency */
1111
class Binders(val tp: BindingType, val next: Binders)
1212

@@ -44,7 +44,7 @@ trait Hashable {
4444
avoidSpecialHashes(hashing.finalizeHash(hashCode, arity))
4545

4646
final def typeHash(bs: Binders, tp: Type): Int =
47-
if (bs == null || tp.stableHash) tp.hash else tp.computeHash(bs)
47+
if (bs == null || tp.hashIsStable) tp.hash else tp.computeHash(bs)
4848

4949
def identityHash(bs: Binders): Int = avoidSpecialHashes(System.identityHashCode(this))
5050

@@ -80,7 +80,7 @@ trait Hashable {
8080
finishHash(bs, hashing.mix(seed, elemHash), arity + 1, tps)
8181
}
8282

83-
83+
8484
protected final def doHash(x: Any): Int =
8585
finishHash(hashing.mix(hashSeed, x.hashCode), 1)
8686

compiler/src/dotty/tools/dotc/core/NameKinds.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,6 @@ object NameKinds {
338338
}
339339
}
340340

341-
/** The kind of names that also encode a variance: 0 for contravariance, 1 for covariance. */
342-
val VariantName: NumberedNameKind = new NumberedNameKind(VARIANT, "Variant") {
343-
def mkString(underlying: TermName, info: ThisInfo) = "-+"(info.num).toString + underlying
344-
}
345-
346341
/** Names of the form N_<outer>. Emitted by inliner, replaced by outer path
347342
* in ExplicitOuter.
348343
*/

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -139,32 +139,8 @@ object NameOps {
139139
name.replace { case ExpandedName(_, unexp) => unexp }
140140
}
141141

142-
/** Remove the variance from the name. */
143-
def invariantName: N = likeSpacedN {
144-
name.replace { case VariantName(invariant, _) => invariant }
145-
}
146-
147142
def errorName: N = likeSpacedN(name ++ nme.ERROR)
148143

149-
/** Map variance value -1, +1 to 0, 1 */
150-
private def varianceToNat(v: Int) = (v + 1) / 2
151-
152-
/** Map 0, 1 to variance value -1, +1 */
153-
private def natToVariance(n: Int) = n * 2 - 1
154-
155-
/** Name with variance prefix: `+` for covariant, `-` for contravariant */
156-
def withVariance(v: Int): N = {
157-
val underlying = name.exclude(VariantName)
158-
likeSpacedN(
159-
if (v == 0) underlying
160-
else VariantName(underlying.toTermName, varianceToNat(v)))
161-
}
162-
163-
/** The variance as implied by the variance prefix, or 0 if there is
164-
* no variance prefix.
165-
*/
166-
def variance: Int = name.collect { case VariantName(_, n) => natToVariance(n) }.getOrElse(0)
167-
168144
def freshened(implicit ctx: Context): N = likeSpacedN {
169145
name.toTermName match {
170146
case ModuleClassName(original) => ModuleClassName(original.freshened)

compiler/src/dotty/tools/dotc/core/NameTags.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ object NameTags extends TastyFormat.NameTags {
4545
case TRAITSETTER => "TRAITSETTER"
4646
case UNIQUE => "UNIQUE"
4747
case DEFAULTGETTER => "DEFAULTGETTER"
48-
case VARIANT => "VARIANT"
4948
case OUTERSELECT => "OUTERSELECT"
5049

5150
case SUPERACCESSOR => "SUPERACCESSOR"

compiler/src/dotty/tools/dotc/core/ParamInfo.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dotty.tools.dotc.core
33
import Names.Name
44
import Contexts.Context
55
import Types.Type
6+
import Variances.{Variance, varianceToInt}
67

78
/** A common super trait of Symbol and LambdaParam.
89
* Used to capture the attributes of type parameters which can be implemented as either.
@@ -35,7 +36,13 @@ trait ParamInfo {
3536
def paramInfoOrCompleter(implicit ctx: Context): Type
3637

3738
/** The variance of the type parameter */
38-
def paramVariance(implicit ctx: Context): Int
39+
def paramVariance(implicit ctx: Context): Variance
40+
41+
/** The variance of the type parameter, as a number -1, 0, +1.
42+
* Bivariant is mapped to 1, i.e. it is treated like Covariant.
43+
*/
44+
final def paramVarianceSign(implicit ctx: Context): Int =
45+
varianceToInt(paramVariance)
3946

4047
/** A type that refers to the parameter */
4148
def paramRef(implicit ctx: Context): Type

0 commit comments

Comments
 (0)