Skip to content

Commit 38fb6c5

Browse files
committed
Refactoring MemberBinding -> TypeParamInfo
Also, drop the notion that RefinedTypes can be type parameters. This is no longer true under the new representation.
1 parent 85da81f commit 38fb6c5

10 files changed

+83
-105
lines changed

src/dotty/tools/dotc/core/MemberBinding.scala

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ object Symbols {
367367
* @param coord The coordinates of the symbol (a position or an index)
368368
* @param id A unique identifier of the symbol (unique per ContextBase)
369369
*/
370-
class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with MemberBinding with printing.Showable {
370+
class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with TypeParamInfo with printing.Showable {
371371

372372
type ThisName <: Name
373373

@@ -489,12 +489,12 @@ object Symbols {
489489
*/
490490
def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition
491491

492-
// MemberBinding methods
492+
// TypeParamInfo methods
493493
def isTypeParam(implicit ctx: Context) = denot.is(TypeParam)
494-
def memberName(implicit ctx: Context): Name = name
495-
def memberBounds(implicit ctx: Context) = denot.info.bounds
496-
def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds
497-
def memberVariance(implicit ctx: Context) = denot.variance
494+
def paramName(implicit ctx: Context): Name = name
495+
def paramBounds(implicit ctx: Context) = denot.info.bounds
496+
def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds
497+
def paramVariance(implicit ctx: Context) = denot.variance
498498

499499
// -------- Printing --------------------------------------------------------
500500

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,14 @@ object TypeApplications {
4646

4747
/** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`?
4848
*/
49-
def varianceConforms(tparam1: MemberBinding, tparam2: MemberBinding)(implicit ctx: Context): Boolean =
50-
varianceConforms(tparam1.memberVariance, tparam2.memberVariance)
49+
def varianceConforms(tparam1: TypeParamInfo, tparam2: TypeParamInfo)(implicit ctx: Context): Boolean =
50+
varianceConforms(tparam1.paramVariance, tparam2.paramVariance)
5151

5252
/** Doe the variances of type parameters `tparams1` conform to the variances
5353
* of corresponding type parameters `tparams2`?
5454
* This is only the case of `tparams1` and `tparams2` have the same length.
5555
*/
56-
def variancesConform(tparams1: List[MemberBinding], tparams2: List[MemberBinding])(implicit ctx: Context): Boolean =
56+
def variancesConform(tparams1: List[TypeParamInfo], tparams2: List[TypeParamInfo])(implicit ctx: Context): Boolean =
5757
tparams1.corresponds(tparams2)(varianceConforms)
5858

5959
/** Extractor for
@@ -95,13 +95,13 @@ object TypeApplications {
9595
refinements = rt :: refinements
9696
tycon = rt.parent.stripTypeVar
9797
}
98-
def collectArgs(tparams: List[MemberBinding],
98+
def collectArgs(tparams: List[TypeParamInfo],
9999
refinements: List[RefinedType],
100100
argBuf: mutable.ListBuffer[Type]): Option[(Type, List[Type])] = refinements match {
101101
case Nil if tparams.isEmpty && argBuf.nonEmpty =>
102102
Some((tycon, argBuf.toList))
103103
case RefinedType(_, rname, rinfo) :: refinements1
104-
if tparams.nonEmpty && rname == tparams.head.memberName =>
104+
if tparams.nonEmpty && rname == tparams.head.paramName =>
105105
collectArgs(tparams.tail, refinements1, argBuf += rinfo.argInfo)
106106
case _ =>
107107
None
@@ -116,12 +116,12 @@ object TypeApplications {
116116

117117
/** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK
118118
*/
119-
def etaExpandIfHK(tparams: List[MemberBinding], args: List[Type])(implicit ctx: Context): List[Type] =
119+
def etaExpandIfHK(tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): List[Type] =
120120
if (tparams.isEmpty) args
121121
else {
122-
def bounds(tparam: MemberBinding) = tparam match {
122+
def bounds(tparam: TypeParamInfo) = tparam match {
123123
case tparam: Symbol => tparam.infoOrCompleter
124-
case tparam: LambdaParam => tparam.memberBounds
124+
case tparam: LambdaParam => tparam.paramBounds
125125
}
126126
args.zipWithConserve(tparams)((arg, tparam) => arg.etaExpandIfHK(bounds(tparam)))
127127
}
@@ -183,7 +183,7 @@ class TypeApplications(val self: Type) extends AnyVal {
183183
* with the bounds on its hk args. See `LambdaAbstract`, where these
184184
* types get introduced, and see `isBoundedLambda` below for the test.
185185
*/
186-
final def typeParams(implicit ctx: Context): List[MemberBinding] = /*>|>*/ track("typeParams") /*<|<*/ {
186+
final def typeParams(implicit ctx: Context): List[TypeParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ {
187187
self match {
188188
case self: ClassInfo =>
189189
self.cls.typeParams
@@ -195,7 +195,7 @@ class TypeApplications(val self: Type) extends AnyVal {
195195
else if (!tsym.isCompleting) tsym.info.typeParams
196196
else Nil
197197
case self: RefinedType =>
198-
self.parent.typeParams.filterNot(_.memberName == self.refinedName)
198+
self.parent.typeParams.filterNot(_.paramName == self.refinedName)
199199
case self: RecType =>
200200
self.parent.typeParams
201201
case _: HKApply | _: SingletonType =>
@@ -210,7 +210,7 @@ class TypeApplications(val self: Type) extends AnyVal {
210210
}
211211

212212
/** If `self` is a higher-kinded type, its type parameters $hk_i, otherwise Nil */
213-
final def hkTypeParams(implicit ctx: Context): List[MemberBinding] =
213+
final def hkTypeParams(implicit ctx: Context): List[TypeParamInfo] =
214214
if (isHK) typeParams else Nil
215215

216216
/** If `self` is a generic class, its type parameter symbols, otherwise Nil */
@@ -450,9 +450,9 @@ class TypeApplications(val self: Type) extends AnyVal {
450450
else {
451451
def adaptArg(arg: Type): Type = arg match {
452452
case arg @ TypeLambda(tparams, body) if
453-
!tparams.corresponds(hkParams)(_.memberVariance == _.memberVariance) &&
453+
!tparams.corresponds(hkParams)(_.paramVariance == _.paramVariance) &&
454454
tparams.corresponds(hkParams)(varianceConforms) =>
455-
TypeLambda(tparams.map(_.memberName), hkParams.map(_.memberVariance))(
455+
TypeLambda(tparams.map(_.paramName), hkParams.map(_.paramVariance))(
456456
tl => arg.paramBounds.map(_.subst(arg, tl).bounds),
457457
tl => arg.resultType.subst(arg, tl)
458458
)
@@ -501,12 +501,12 @@ class TypeApplications(val self: Type) extends AnyVal {
501501
* @param args = `U1, ..., Un`
502502
* @param tparams are assumed to be the type parameters of `T`.
503503
*/
504-
final def appliedTo(args: List[Type], typParams: List[MemberBinding])(implicit ctx: Context): Type = {
505-
def matchParams(t: Type, tparams: List[MemberBinding], args: List[Type])(implicit ctx: Context): Type = args match {
504+
final def appliedTo(args: List[Type], typParams: List[TypeParamInfo])(implicit ctx: Context): Type = {
505+
def matchParams(t: Type, tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): Type = args match {
506506
case arg :: args1 =>
507507
try {
508508
val tparam :: tparams1 = tparams
509-
matchParams(RefinedType(t, tparam.memberName, arg.toBounds(tparam)), tparams1, args1)
509+
matchParams(RefinedType(t, tparam.paramName, arg.toBounds(tparam)), tparams1, args1)
510510
} catch {
511511
case ex: MatchError =>
512512
println(s"applied type mismatch: $self with underlying ${self.underlyingIfProxy}, args = $args, typeParams = $typParams") // !!! DEBUG
@@ -563,11 +563,11 @@ class TypeApplications(val self: Type) extends AnyVal {
563563
/** Turn this type, which is used as an argument for
564564
* type parameter `tparam`, into a TypeBounds RHS
565565
*/
566-
final def toBounds(tparam: MemberBinding)(implicit ctx: Context): TypeBounds = self match {
566+
final def toBounds(tparam: TypeParamInfo)(implicit ctx: Context): TypeBounds = self match {
567567
case self: TypeBounds => // this can happen for wildcard args
568568
self
569569
case _ =>
570-
val v = tparam.memberVariance
570+
val v = tparam.paramVariance
571571
/* Not neeeded.
572572
if (v > 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.upper(self)
573573
else if (v < 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.lower(self)

src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
392392
// so the bounds checking should look like this:
393393
//
394394
// tparams1.corresponds(tparams2)((tparam1, tparam2) =>
395-
// isSubType(tparam2.memberBounds.subst(tp2, tp1), tparam1.memberBounds))
395+
// isSubType(tparam2.paramBounds.subst(tp2, tp1), tparam1.paramBounds))
396396
//
397397
// But that would invalidate a pattern such as
398398
// `[X0 <: Number] -> Number <:< [X0] -> Any`
@@ -685,10 +685,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
685685
/** Subtype test for corresponding arguments in `args1`, `args2` according to
686686
* variances in type parameters `tparams`.
687687
*/
688-
def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[MemberBinding]): Boolean =
688+
def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[TypeParamInfo]): Boolean =
689689
if (args1.isEmpty) args2.isEmpty
690690
else args2.nonEmpty && {
691-
val v = tparams.head.memberVariance
691+
val v = tparams.head.paramVariance
692692
(v > 0 || isSubType(args2.head, args1.head)) &&
693693
(v < 0 || isSubType(args1.head, args2.head))
694694
}
@@ -698,7 +698,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
698698
* - the type parameters of `B` match one-by-one the variances of `tparams`,
699699
* - `B` satisfies predicate `p`.
700700
*/
701-
private def testLifted(tp1: Type, tp2: Type, tparams: List[MemberBinding], p: Type => Boolean): Boolean = {
701+
private def testLifted(tp1: Type, tp2: Type, tparams: List[TypeParamInfo], p: Type => Boolean): Boolean = {
702702
val classBounds = tp2.classSymbols
703703
def recur(bcs: List[ClassSymbol]): Boolean = bcs match {
704704
case bc :: bcs1 =>
@@ -1215,19 +1215,19 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
12151215
val tparams2 = tp2.typeParams
12161216
if (tparams1.isEmpty)
12171217
if (tparams2.isEmpty) op(tp1, tp2)
1218-
else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.memberBoundsAsSeenFrom(tp2))))
1218+
else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramBoundsAsSeenFrom(tp2))))
12191219
else if (tparams2.isEmpty)
1220-
original(tp1.appliedTo(tp1.typeParams.map(_.memberBoundsAsSeenFrom(tp1))), tp2)
1220+
original(tp1.appliedTo(tp1.typeParams.map(_.paramBoundsAsSeenFrom(tp1))), tp2)
12211221
else {
12221222
val numArgs = tparams1.length
12231223
def argRefs(tl: GenericType) = List.range(0, numArgs).map(PolyParam(tl, _))
12241224
TypeLambda(
12251225
paramNames = tpnme.syntheticLambdaParamNames(numArgs),
12261226
variances = (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
1227-
(tparam1.memberVariance + tparam2.memberVariance) / 2))(
1227+
(tparam1.paramVariance + tparam2.paramVariance) / 2))(
12281228
paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
1229-
tl.lifted(tparams1, tparam1.memberBoundsAsSeenFrom(tp1)).bounds &
1230-
tl.lifted(tparams2, tparam2.memberBoundsAsSeenFrom(tp2)).bounds),
1229+
tl.lifted(tparams1, tparam1.paramBoundsAsSeenFrom(tp1)).bounds &
1230+
tl.lifted(tparams2, tparam2.paramBoundsAsSeenFrom(tp2)).bounds),
12311231
resultTypeExp = tl =>
12321232
original(tl.lifted(tparams1, tp1).appliedTo(argRefs(tl)),
12331233
tl.lifted(tparams2, tp2).appliedTo(argRefs(tl))))
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package dotty.tools.dotc.core
2+
3+
import Names.Name
4+
import Contexts.Context
5+
import Types.{Type, TypeBounds}
6+
7+
/** A common super trait of Symbol and LambdaParam.
8+
* Used to capture the attributes of type parameters which can be implemented as either.
9+
*/
10+
trait TypeParamInfo {
11+
12+
/** Is this the info of a type parameter? Might be wrong for symbols */
13+
def isTypeParam(implicit ctx: Context): Boolean
14+
15+
/** The name of the type parameter */
16+
def paramName(implicit ctx: Context): Name
17+
18+
/** The info of the type parameter */
19+
def paramBounds(implicit ctx: Context): TypeBounds
20+
21+
/** The info of the type parameter as seen from a prefix type.
22+
* This can be different from `memberInfo` if the binding
23+
* is a type symbol of a class.
24+
*/
25+
def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds
26+
27+
/** The variance of the type parameter */
28+
def paramVariance(implicit ctx: Context): Int
29+
}

src/dotty/tools/dotc/core/Types.scala

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,8 @@ object Types {
116116
case TypeAlias(tp) => tp.isRef(sym)
117117
case _ => this1.symbol eq sym
118118
}
119-
case this1: RefinedType =>
120-
!this1.isTypeParam && this1.parent.isRef(sym)
121-
case this1: RecType =>
122-
this1.parent.isRef(sym)
123-
case _ =>
124-
false
119+
case this1: RefinedOrRecType => this1.parent.isRef(sym)
120+
case _ => false
125121
}
126122

127123
/** Is this type a (neither aliased nor applied) reference to class `sym`? */
@@ -939,7 +935,7 @@ object Types {
939935
tp.underlying.underlyingClassRef(refinementOK)
940936
case tp: RefinedType =>
941937
def isParamName = tp.classSymbol.typeParams.exists(_.name == tp.refinedName)
942-
if (refinementOK || tp.isTypeParam || isParamName) tp.underlying.underlyingClassRef(refinementOK)
938+
if (refinementOK || isParamName) tp.underlying.underlyingClassRef(refinementOK)
943939
else NoType
944940
case tp: RecType =>
945941
tp.underlying.underlyingClassRef(refinementOK)
@@ -2099,8 +2095,7 @@ object Types {
20992095
* @param infoFn: A function that produces the info of the refinement declaration,
21002096
* given the refined type itself.
21012097
*/
2102-
abstract case class RefinedType(parent: Type, refinedName: Name, refinedInfo: Type)
2103-
extends RefinedOrRecType with BindingType with MemberBinding {
2098+
abstract case class RefinedType(parent: Type, refinedName: Name, refinedInfo: Type) extends RefinedOrRecType {
21042099

21052100
override def underlying(implicit ctx: Context) = parent
21062101

@@ -2120,17 +2115,6 @@ object Types {
21202115
if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo)
21212116
else parent
21222117

2123-
// MemberBinding methods
2124-
// TODO: Needed?
2125-
def isTypeParam(implicit ctx: Context) = refinedInfo match {
2126-
case tp: TypeBounds => tp.isBinding
2127-
case _ => false
2128-
}
2129-
def memberName(implicit ctx: Context) = refinedName
2130-
def memberBounds(implicit ctx: Context) = refinedInfo.bounds
2131-
def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = memberBounds
2132-
def memberVariance(implicit ctx: Context) = BindingKind.toVariance(refinedInfo.bounds.bindingKind)
2133-
21342118
override def equals(that: Any) = that match {
21352119
case that: RefinedType =>
21362120
this.parent == that.parent &&
@@ -2579,7 +2563,7 @@ object Types {
25792563

25802564
def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): GenericType
25812565

2582-
def lifted(tparams: List[MemberBinding], t: Type)(implicit ctx: Context): Type =
2566+
def lifted(tparams: List[TypeParamInfo], t: Type)(implicit ctx: Context): Type =
25832567
tparams match {
25842568
case LambdaParam(poly, _) :: _ =>
25852569
t.subst(poly, this)
@@ -2666,12 +2650,12 @@ object Types {
26662650
}
26672651

26682652
/** The parameter of a type lambda */
2669-
case class LambdaParam(tl: TypeLambda, n: Int) extends MemberBinding {
2653+
case class LambdaParam(tl: TypeLambda, n: Int) extends TypeParamInfo {
26702654
def isTypeParam(implicit ctx: Context) = true
2671-
def memberName(implicit ctx: Context): TypeName = tl.paramNames(n)
2672-
def memberBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n)
2673-
def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = memberBounds
2674-
def memberVariance(implicit ctx: Context): Int = tl.variances(n)
2655+
def paramName(implicit ctx: Context): TypeName = tl.paramNames(n)
2656+
def paramBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n)
2657+
def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = paramBounds
2658+
def paramVariance(implicit ctx: Context): Int = tl.variances(n)
26752659
def toArg: Type = PolyParam(tl, n)
26762660
}
26772661

@@ -2712,7 +2696,7 @@ object Types {
27122696
case _ => defn.AnyType
27132697
}
27142698

2715-
def typeParams(implicit ctx: Context): List[MemberBinding] = {
2699+
def typeParams(implicit ctx: Context): List[TypeParamInfo] = {
27162700
val tparams = tycon.typeParams
27172701
if (tparams.isEmpty) TypeLambda.any(args.length).typeParams else tparams
27182702
}
@@ -3530,10 +3514,10 @@ object Types {
35303514
if (inst.exists) apply(inst) else tp
35313515

35323516
case tp: HKApply =>
3533-
def mapArg(arg: Type, tparam: MemberBinding): Type = {
3517+
def mapArg(arg: Type, tparam: TypeParamInfo): Type = {
35343518
val saved = variance
3535-
if (tparam.memberVariance < 0) variance = -variance
3536-
else if (tparam.memberVariance == 0) variance = 0
3519+
if (tparam.paramVariance < 0) variance = -variance
3520+
else if (tparam.paramVariance == 0) variance = 0
35373521
try this(arg)
35383522
finally variance = saved
35393523
}

src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ class TreePickler(pickler: TastyPickler) {
257257
case tpe: TypeLambda =>
258258
writeByte(LAMBDAtype)
259259
val paramNames = tpe.typeParams.map(tparam =>
260-
varianceToPrefix(tparam.memberVariance) +: tparam.memberName)
260+
varianceToPrefix(tparam.paramVariance) +: tparam.paramName)
261261
pickleMethodic(tpe.resultType, paramNames, tpe.paramBounds)
262262
case tpe: MethodType if richTypes =>
263263
writeByte(METHODtype)

src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ trait TypeAssigner {
9898
val base = apply(tycon)
9999
var args = tp.baseArgInfos(base.typeSymbol)
100100
if (base.typeParams.length != args.length)
101-
args = base.typeParams.map(_.memberBounds)
101+
args = base.typeParams.map(_.paramBounds)
102102
base.appliedTo(args)
103103
case tp @ RefinedType(parent, name, rinfo) if variance > 0 =>
104104
val parent1 = apply(tp.parent)
@@ -412,7 +412,7 @@ trait TypeAssigner {
412412
def refineNamed(tycon: Type, arg: Tree) = arg match {
413413
case ast.Trees.NamedArg(name, argtpt) =>
414414
// Dotty deviation: importing ast.Trees._ and matching on NamedArg gives a cyclic ref error
415-
val tparam = tparams.find(_.memberName == name) match {
415+
val tparam = tparams.find(_.paramName == name) match {
416416
case Some(tparam) => tparam
417417
case none => ntparams.find(_.name == name).getOrElse(NoSymbol)
418418
}

0 commit comments

Comments
 (0)