@@ -3564,39 +3564,55 @@ object Types {
3564
3564
pt => List .fill(n)(TypeBounds .empty), pt => defn.AnyType )
3565
3565
3566
3566
override def fromParams [PI <: ParamInfo .Of [TypeName ]](params : List [PI ], resultType : Type )(implicit ctx : Context ): Type =
3567
- fromParams(params, resultType, useVariances = resultType.isInstanceOf [TypeBounds ])
3567
+ resultType match
3568
+ case bounds : TypeBounds => boundsFromParams(params, bounds)
3569
+ case _ => super .fromParams(params, resultType)
3568
3570
3569
3571
/** Distributes Lambda inside type bounds. Examples:
3570
3572
*
3571
3573
* type T[X] = U becomes type T = [X] -> U
3572
3574
* type T[X] <: U becomes type T >: Nothing <: ([X] -> U)
3573
3575
* type T[X] >: L <: U becomes type T >: ([X] -> L) <: ([X] -> U)
3574
3576
*
3575
- * @param useVariances If true, set parameter variances of the type lambda to be as in `params`,
3576
- * If false, TypeBounds types and match aliases aways get their variances set
3577
- * and type aliases get variances set if some parameter is not invariant,
3578
- * but variances of parameters of other types are determined structurally,
3579
- * by looking how the parameter is used in the result type.
3577
+ * The variances of regular TypeBounds types, as well as of match aliases
3578
+ * and of opaque aliases are always determined from the given parameters
3579
+ * `params`. The variances of other type aliases are determined from
3580
+ * the given parameters only if one of these parameters carries a `+`
3581
+ * or `-` variance annotation. Type aliases without variance annotation
3582
+ * are treated structurally. That is, their parameter variances are
3583
+ * determined by how the parameter(s) appear in the result type.
3584
+ *
3585
+ * Examples:
3586
+ *
3587
+ * type T[X] >: A // X is invariant
3588
+ * type T[X] <: List[X] // X is invariant
3589
+ * type T[X] = List[X] // X is covariant (determined structurally)
3590
+ * opaque type T[X] = List[X] // X is invariant
3591
+ * opaque type T[+X] = List[X] // X is covariant
3592
+ * type T[A, B] = A => B // A is contravariant, B is covariant (determined structurally)
3593
+ * type T[A, +B] = A => B // A is invariant, B is covariant
3580
3594
*/
3581
- def fromParams [PI <: ParamInfo .Of [TypeName ]](params : List [PI ], resultType : Type , useVariances : Boolean )(implicit ctx : Context ): Type = {
3595
+ def boundsFromParams [PI <: ParamInfo .Of [TypeName ]](params : List [PI ], bounds : TypeBounds )(implicit ctx : Context ): TypeBounds = {
3582
3596
def expand (tp : Type , useVariances : Boolean ) =
3583
3597
if params.nonEmpty && useVariances then
3584
3598
apply(params.map(_.paramName), params.map(_.paramVariance))(
3585
3599
tl => params.map(param => toPInfo(tl.integrate(params, param.paramInfo))),
3586
3600
tl => tl.integrate(params, tp))
3587
3601
else
3588
3602
super .fromParams(params, tp)
3589
- resultType match {
3590
- case rt : MatchAlias =>
3591
- rt.derivedAlias(expand(rt.alias, true ))
3592
- case rt : TypeAlias =>
3593
- rt.derivedAlias(expand(rt.alias, params.exists(! _.paramVariance.isEmpty)))
3594
- case rt @ TypeBounds (lo, hi) =>
3595
- rt.derivedTypeBounds(
3596
- if (lo.isRef(defn.NothingClass )) lo else expand(lo, true ),
3603
+ def isOpaqueAlias = params match
3604
+ case (param : Symbol ) :: _ => param.owner.is(Opaque )
3605
+ case _ => false
3606
+ bounds match {
3607
+ case bounds : MatchAlias =>
3608
+ bounds.derivedAlias(expand(bounds.alias, true ))
3609
+ case bounds : TypeAlias =>
3610
+ bounds.derivedAlias(expand(bounds.alias,
3611
+ isOpaqueAlias | params.exists(! _.paramVariance.isEmpty)))
3612
+ case TypeBounds (lo, hi) =>
3613
+ bounds.derivedTypeBounds(
3614
+ if lo.isRef(defn.NothingClass ) then lo else expand(lo, true ),
3597
3615
expand(hi, true ))
3598
- case rt =>
3599
- expand(rt, useVariances)
3600
3616
}
3601
3617
}
3602
3618
}
0 commit comments