Skip to content

[WIP] Direct representation of higher-kinded types #1337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 142 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
468b499
Record binding kind in TypeBounds
odersky May 24, 2016
2d8d291
Allow refinements of new types
odersky May 24, 2016
10ef004
Allow general recursion in refined types.
odersky May 25, 2016
3c99610
Refinements to refinement types
odersky May 25, 2016
461fe3d
Add type lambdas
odersky May 26, 2016
3960710
Better printing of skolems
odersky May 26, 2016
a3a6108
New type lambda scheme for hk types
odersky May 26, 2016
e768331
Add mapInfo method to Denotations
odersky May 27, 2016
c7fa021
Introduce recursive types
odersky May 27, 2016
7d3b4de
Use recursive types also when unpickling from Scala 2.x
odersky May 27, 2016
96f6bc6
Abstract type parameters out from type symbols
odersky May 27, 2016
4b912db
Fix toVariance in MemberBinding
odersky May 27, 2016
6b9e7d8
Disable checkInst in RecType
odersky May 27, 2016
67b4917
Simplify RecType.closeOver
odersky May 27, 2016
7c59785
Rename MemberInfo -> MemberBinding
odersky May 27, 2016
7a92cd5
Add printing of type lambda trees
odersky May 27, 2016
c9daca0
Replace MemberBinding # memberInfo by memberBounds
odersky May 27, 2016
ddc3a81
Fix printing of type lambdas
odersky May 27, 2016
eb3f1a6
Remove special case in parser
odersky May 27, 2016
b6f9305
[WIP] Tenantive new HK scheme.
odersky May 30, 2016
444e182
Avoid crasher in derivedTypeParams
odersky May 31, 2016
bc51e63
Fix printing of type lambdas
odersky May 31, 2016
b1ee403
Remove printlns
odersky May 31, 2016
fed3150
Revise logic in type comparer for new HK scheme
odersky May 31, 2016
56d2dd3
Rmove over-zealous check
odersky May 31, 2016
828b231
Turn on new hk scheme
odersky Jun 1, 2016
ec0ce3a
Swap order of tests in lookupRefined
odersky Jun 1, 2016
e17ca87
Change joins of BindingKinds
odersky Jun 1, 2016
a7fb8a7
Fix printing of type lambdas under new hk scheme
odersky Jun 2, 2016
cd51707
refine isRef for hk type
odersky Jun 2, 2016
88f4272
Fix withBindingKind for type aliases
odersky Jun 2, 2016
df73535
Multiple fixes to BetaReduce
odersky Jun 2, 2016
a0afd49
Fix logic for hk subtype tests
odersky Jun 2, 2016
cbf52d1
Make isHK more precise
odersky Jun 2, 2016
e433fe9
Beta-reduce when simplifying
odersky Jun 2, 2016
0de8705
Make etaExpandIfHk work for non-symbol type params
odersky Jun 2, 2016
7d8457d
Avoid stackoverflows for `Rep[T] = T`.
odersky Jun 2, 2016
06f916e
Refinement of cycle avoidance
odersky Jun 3, 2016
194f5d3
Don't map info of SkolemTypes in type maps
odersky Jun 3, 2016
1a656a1
Handle LazyRefs in BetaReduce
odersky Jun 3, 2016
c4fc98b
Fix^2 of asMemberOf
odersky Jun 3, 2016
5ea78e4
Try to beta-reduce bounds before adding to a constraint.
odersky Jun 3, 2016
8fd0e0f
More subtle handling of LazyRefs in BetaReduce
odersky Jun 4, 2016
8eb98a8
Another refinement to asMemberOf
odersky Jun 4, 2016
6068e7a
Drop isSafe test from BetaReduce
odersky Jun 4, 2016
20ebc13
Normalize RecTypes on creation to avoid cycles.
odersky Jun 4, 2016
6afe257
Add a second betaReduce
odersky Jun 4, 2016
1255fb8
Adapt widenForMatchSelector to new HK scheme
odersky Jun 5, 2016
bdf7f3e
Fix typeParams for abstract types under completion
odersky Jun 5, 2016
d5771da
Swap subtype tests
odersky Jun 6, 2016
9e14d74
Make underlyingClassRef work for hk types under new scheme.
odersky Jun 6, 2016
76f7563
Esnure that toAvoid does not creat hk from * types
odersky Jun 6, 2016
2b70615
Let getClass return a * type
odersky Jun 6, 2016
757f117
Generalize typeParamSymbols
odersky Jun 6, 2016
55ff0b5
Eta-expand unapplied types that have type parameters
odersky Jun 6, 2016
ec11b0b
Check kinds of type parameters
odersky Jun 6, 2016
de29cd1
Restrict betaReduce to hk applications
odersky Jun 6, 2016
9b21b46
Handle LazyRefs conservatively in isReferredTo
odersky Jun 7, 2016
226cdb9
Optionally, check kinds match for & and |
odersky Jun 7, 2016
7329957
Avoid infinite recursion when comparing recursive types.
odersky Jun 7, 2016
6fac433
Remove debug println
odersky Jun 7, 2016
6ed6857
Make typeParams more defensive
odersky Jun 7, 2016
7dc3135
Fix condition for lambda abstracting in Namer
odersky Jun 7, 2016
c896a83
Refinement for knownHK for PolyParams
odersky Jun 7, 2016
e38541b
Remove debug println
odersky Jun 7, 2016
db4d934
Make TypeAccumulators follow LazyRefs
odersky Jun 7, 2016
3560e56
Add normalizeHkApply to homogenize
odersky Jun 8, 2016
1844c1d
Avoid creating dependent function types for closures
odersky Jun 8, 2016
a6caf1c
Generalize compareHkApply to types other than PolyParams
odersky Jun 8, 2016
392090a
Homogenize skolem types
odersky Jun 8, 2016
5182a58
Change test to make it pass
odersky Jun 8, 2016
5e448ff
Disable named parameter tests
odersky Jun 8, 2016
5a20984
Fix merge errors
odersky Jun 8, 2016
9887c43
Revert "Generalize compareHkApply to types other than PolyParams"
odersky Jun 9, 2016
b4f21d0
Deal with nested findMember calls over the same RecType
odersky Jun 9, 2016
7cc0308
Add explanation why generizing compreHkApply is not needed.
odersky Jun 9, 2016
b88cfec
Fix comments
odersky Jun 9, 2016
7abd0cc
Add TODO comment in TreePickler
odersky Jun 9, 2016
794bb02
Swap order of subtype tests
odersky Jun 9, 2016
7c99c8a
Cleanups
odersky Jun 10, 2016
4c51505
Smarter handling of LazyRefs in betaReduce
odersky Jun 10, 2016
eb6cfb4
Optimize RecType/RecType comparisons
odersky Jun 10, 2016
6d6afbf
Fi compareHkLambda
odersky Jun 11, 2016
745a718
Remove old hk scheme
odersky Jun 11, 2016
79a7976
Simoplify RefinedType
odersky Jun 11, 2016
57bf237
Simplify typeParams
odersky Jun 12, 2016
e735bf4
Remove unused code and out of date comments
odersky Jun 13, 2016
c2c181c
Start new, direct HK scheme
odersky Jun 13, 2016
3a7d27a
New types for hk types
odersky Jun 13, 2016
6e83dfe
Pickling/unpickling of type lambdas
odersky Jun 13, 2016
1e75d42
Typemaps and accumulators for TypeLambda and HKApply
odersky Jun 13, 2016
ee8f472
Methods for handling new hk types
odersky Jun 13, 2016
2cb8abf
Handle HKApply in variance calculations
odersky Jun 13, 2016
18b3406
Label more redundant definitions with OLD
odersky Jun 13, 2016
f7396ca
Add type erasure for type lambdas
odersky Jun 13, 2016
8cec279
Fix appliedTo and typeParams
odersky Jun 13, 2016
abd232f
Make Constraint#bounds work for aliases
odersky Jun 14, 2016
594af39
Fix higher kinded subtyping tests
odersky Jun 18, 2016
0bea597
Fix printing of type lambda trees and types
odersky Jun 18, 2016
62db4a7
Add existential type elimination for HKApply
odersky Jun 18, 2016
d5c2006
Handle hk applications in normalizeToRefs
odersky Jun 18, 2016
f0a4ac5
Various hk related fixes in types
odersky Jun 18, 2016
d39e474
Fix adaptation of type lambdas
odersky Jun 18, 2016
4df1ab7
Tweaks to appliedTo
odersky Jun 19, 2016
1716379
Refactoring of PolyType and TypeLambda
odersky Jun 19, 2016
dfde338
Always consider EtaExpansions in appliedTo
odersky Jun 20, 2016
1420ff0
Change underlying of HKApply
odersky Jun 20, 2016
6be9d1d
Ensure wildApprox maintains kinds
odersky Jun 20, 2016
0a73669
Handle TypeLambdas in findMember
odersky Jun 20, 2016
e5f1ca2
Avoid cyclic errors when reading nsc.Global
odersky Jun 21, 2016
0119da5
Refactor handling of unpickled type params
odersky Jun 21, 2016
ea56a23
Revert auto-healing in derivedAppliedType
odersky Jun 21, 2016
f9005cc
Smallish fixes to type applications
odersky Jun 21, 2016
f050d57
Allow for HK types in widenForMatchSelector
odersky Jun 22, 2016
9ffc6e7
Drop bounds checking for type lambdas
odersky Jun 22, 2016
449b306
Skip typeBounds when computing upperBound
odersky Jun 22, 2016
da18601
When comparing types revert eta-expansion as needed
odersky Jun 26, 2016
9a9ac10
Beta-reduce with wildcard arguments if this is safe.
odersky Jun 26, 2016
9f2e56f
Take hk types into account for liftToClasses
odersky Jun 26, 2016
63db7ca
Remove debug output
odersky Jun 26, 2016
4bbfc3b
Fix appliedTo for aliasTypes
odersky Jun 27, 2016
0df6d24
Handle findMember for unreduced hk types.
odersky Jun 27, 2016
7730b73
Handle WildcardType in liftToClasses
odersky Jun 28, 2016
61bb28d
Drop debug output in printer
odersky Jun 28, 2016
cacd593
Don't make * types higher-kinded in avoid
odersky Jun 28, 2016
685540d
Fix tests
odersky Jun 28, 2016
59bd5e3
Don't dealias when applying types
odersky Jun 28, 2016
26fcafc
Reduce Nothing[...] to Nothing
odersky Jun 28, 2016
5f3b19b
Follow aliases in isMatchingApply
odersky Jun 28, 2016
392017c
Avoid comparing with TypeBounds in compareHkApply
odersky Jun 28, 2016
4ade3c1
Generalize kind adaption in liftIfHK
odersky Jun 28, 2016
11d0ff3
Special case for TypeRefs in upperbound
odersky Jun 28, 2016
0a29c27
Drop assertion in TypeMap
odersky Jun 28, 2016
ec7fad3
Enable new hk scheme.
odersky Jun 28, 2016
4377aaa
Fix parameter unpickling
odersky Jun 28, 2016
d0625ab
Remove refinement encoding of hk types
odersky Jun 29, 2016
c26aa8f
Make printing package ids more robost
odersky Jun 29, 2016
82d042f
Make Denotation#bringForward more robost
odersky Jun 29, 2016
1fb965c
Handle signatures over uninstantiated type variables
odersky Jun 29, 2016
85da81f
Drop kludge of "normalizing" in derivedRefinedType
odersky Jun 29, 2016
38fb6c5
Refactoring MemberBinding -> TypeParamInfo
odersky Jun 29, 2016
127c8a6
Get rid of BindingKind
odersky Jun 29, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/SyntaxSummary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ grammar.
ClassQualifier ::= `[' id `]'

Type ::= FunArgTypes `=>' Type Function(ts, t)
| HkTypeParamClause `->' Type TypeLambda(ps, t)
| InfixType
FunArgTypes ::= InfixType
| `(' [ FunArgType {`,' FunArgType } ] `)'
Expand Down Expand Up @@ -125,7 +126,6 @@ grammar.
TypeParamBounds ::= TypeBounds {`<%' Type} {`:' Type} ContextBounds(typeBounds, tps)

Expr ::= FunParams `=>' Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr)
| Expr1
FunParams ::= Bindings
| [`implicit'] id
| `_'
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ object desugar {
val relocate = new TypeMap {
val originalOwner = sym.owner
def apply(tp: Type) = tp match {
case tp: NamedType if tp.symbol.owner eq originalOwner =>
case tp: NamedType if tp.symbol.exists && (tp.symbol.owner eq originalOwner) =>
val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next
var local = defctx.denotNamed(tp.name).suchThat(_ is ParamOrAccessor).symbol
if (local.exists) (defctx.owner.thisType select local).dealias
Expand Down
16 changes: 16 additions & 0 deletions src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,12 @@ object Trees {
def forwardTo = tpt
}

/** [typeparams] -> tpt */
case class TypeLambdaTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])
extends TypTree[T] {
type ThisTree[-T >: Untyped] = TypeLambdaTree[T]
}

/** => T */
case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])
extends TypTree[T] {
Expand Down Expand Up @@ -851,6 +857,7 @@ object Trees {
type OrTypeTree = Trees.OrTypeTree[T]
type RefinedTypeTree = Trees.RefinedTypeTree[T]
type AppliedTypeTree = Trees.AppliedTypeTree[T]
type TypeLambdaTree = Trees.TypeLambdaTree[T]
type ByNameTypeTree = Trees.ByNameTypeTree[T]
type TypeBoundsTree = Trees.TypeBoundsTree[T]
type Bind = Trees.Bind[T]
Expand Down Expand Up @@ -1028,6 +1035,10 @@ object Trees {
case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree
case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args))
}
def TypeLambdaTree(tree: Tree)(tparams: List[TypeDef], body: Tree): TypeLambdaTree = tree match {
case tree: TypeLambdaTree if (tparams eq tree.tparams) && (body eq tree.body) => tree
case _ => finalize(tree, untpd.TypeLambdaTree(tparams, body))
}
def ByNameTypeTree(tree: Tree)(result: Tree): ByNameTypeTree = tree match {
case tree: ByNameTypeTree if result eq tree.result => tree
case _ => finalize(tree, untpd.ByNameTypeTree(result))
Expand Down Expand Up @@ -1160,6 +1171,8 @@ object Trees {
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
case AppliedTypeTree(tpt, args) =>
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
case TypeLambdaTree(tparams, body) =>
cpy.TypeLambdaTree(tree)(transformSub(tparams), transform(body))
case ByNameTypeTree(result) =>
cpy.ByNameTypeTree(tree)(transform(result))
case TypeBoundsTree(lo, hi) =>
Expand Down Expand Up @@ -1264,6 +1277,9 @@ object Trees {
this(this(x, tpt), refinements)
case AppliedTypeTree(tpt, args) =>
this(this(x, tpt), args)
case TypeLambdaTree(tparams, body) =>
implicit val ctx: Context = localCtx
this(this(x, tparams), body)
case ByNameTypeTree(result) =>
this(x, result)
case TypeBoundsTree(lo, hi) =>
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
private def ta(implicit ctx: Context) = ctx.typeAssigner

def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = Modifiers(
sym.flags & ModifierFlags,
sym.flags & (if (sym.isType) ModifierFlags | VarianceFlags else ModifierFlags),
if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
sym.annotations map (_.tree))

Expand Down
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right)
def RefinedTypeTree(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = new RefinedTypeTree(tpt, refinements)
def AppliedTypeTree(tpt: Tree, args: List[Tree]): AppliedTypeTree = new AppliedTypeTree(tpt, args)
def TypeLambdaTree(tparams: List[TypeDef], body: Tree): TypeLambdaTree = new TypeLambdaTree(tparams, body)
def ByNameTypeTree(result: Tree): ByNameTypeTree = new ByNameTypeTree(result)
def TypeBoundsTree(lo: Tree, hi: Tree): TypeBoundsTree = new TypeBoundsTree(lo, hi)
def Bind(name: Name, body: Tree): Bind = new Bind(name, body)
Expand Down
7 changes: 7 additions & 0 deletions src/dotty/tools/dotc/config/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ object Config {
*/
final val checkProjections = false

/** If this flag is set it is checked that &/| only apply to types
* that are either both hk types or both * types. Should be used
* only for debugging as there a generic class without arguments
* can be produced in an And by Implicits.liftToClasses.
*/
final val checkKinds = false

/** The recursion depth for showing a summarized string */
final val summarizeDepth = 2

Expand Down
10 changes: 5 additions & 5 deletions src/dotty/tools/dotc/core/Constraint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ abstract class Constraint extends Showable {
type This <: Constraint

/** Does the constraint's domain contain the type parameters of `pt`? */
def contains(pt: PolyType): Boolean
def contains(pt: GenericType): Boolean

/** Does the constraint's domain contain the type parameter `param`? */
def contains(param: PolyParam): Boolean
Expand Down Expand Up @@ -79,7 +79,7 @@ abstract class Constraint extends Showable {
* satisfiability but will solved to give instances of
* type variables.
*/
def add(poly: PolyType, tvars: List[TypeVar])(implicit ctx: Context): This
def add(poly: GenericType, tvars: List[TypeVar])(implicit ctx: Context): This

/** A new constraint which is derived from this constraint by updating
* the entry for parameter `param` to `tp`.
Expand Down Expand Up @@ -122,13 +122,13 @@ abstract class Constraint extends Showable {
* entry array, but is going to be removed at the same step,
* or -1 if no such parameter exists.
*/
def isRemovable(pt: PolyType, removedParam: Int = -1): Boolean
def isRemovable(pt: GenericType, removedParam: Int = -1): Boolean

/** A new constraint with all entries coming from `pt` removed. */
def remove(pt: PolyType)(implicit ctx: Context): This
def remove(pt: GenericType)(implicit ctx: Context): This

/** The polytypes constrained by this constraint */
def domainPolys: List[PolyType]
def domainPolys: List[GenericType]

/** The polytype parameters constrained by this constraint */
def domainParams: List[PolyParam]
Expand Down
15 changes: 11 additions & 4 deletions src/dotty/tools/dotc/core/ConstraintHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Types._, Contexts._, Symbols._
import Decorators._
import config.Config
import config.Printers._
import TypeApplications.EtaExpansion
import collection.mutable

/** Methods for adding constraints and solving them.
Expand Down Expand Up @@ -193,9 +194,9 @@ trait ConstraintHandling {
}

/** The current bounds of type parameter `param` */
final def bounds(param: PolyParam): TypeBounds = constraint.entry(param) match {
case bounds: TypeBounds => bounds
case _ => param.binder.paramBounds(param.paramNum)
final def bounds(param: PolyParam): TypeBounds = {
val e = constraint.entry(param)
if (e.exists) e.bounds else param.binder.paramBounds(param.paramNum)
}

/** Add polytype `pt`, possibly with type variables `tvars`, to current constraint
Expand Down Expand Up @@ -293,7 +294,13 @@ trait ConstraintHandling {
case bound: PolyParam if constraint contains bound =>
addParamBound(bound)
case _ =>
val pbound = prune(bound)
var pbound = prune(bound)
if (pbound.isHK && !param.isHK) {
param match {
case EtaExpansion(tycon) if tycon.symbol.isClass => pbound = tycon
case _ =>
}
}
pbound.exists && (
if (fromBelow) addLowerBound(param, pbound) else addUpperBound(param, pbound))
}
Expand Down
73 changes: 4 additions & 69 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,17 @@ class Definitions {
}

private def newPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int,
resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = {
resultTypeFn: GenericType => Type, flags: FlagSet = EmptyFlags) = {
val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount)
val tparamBounds = tparamNames map (_ => TypeBounds.empty)
val ptype = PolyType(tparamNames)(_ => tparamBounds, resultTypeFn)
newMethod(cls, name, ptype, flags)
}

private def newT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) =
private def newT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: GenericType => Type, flags: FlagSet) =
newPolyMethod(cls, name, 1, resultTypeFn, flags)

private def newT1EmptyParamsMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) =
private def newT1EmptyParamsMethod(cls: ClassSymbol, name: TermName, resultTypeFn: GenericType => Type, flags: FlagSet) =
newPolyMethod(cls, name, 1, pt => MethodType(Nil, resultTypeFn(pt)), flags)

private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[TypeRef] = {
Expand Down Expand Up @@ -167,7 +167,7 @@ class Definitions {
lazy val Any_hashCode = newMethod(AnyClass, nme.hashCode_, MethodType(Nil, IntType))
lazy val Any_toString = newMethod(AnyClass, nme.toString_, MethodType(Nil, StringType))
lazy val Any_## = newMethod(AnyClass, nme.HASHHASH, ExprType(IntType), Final)
lazy val Any_getClass = newMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef), Final)
lazy val Any_getClass = newMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
lazy val Any_isInstanceOf = newT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
lazy val Any_asInstanceOf = newT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, PolyParam(_, 0), Final)

Expand Down Expand Up @@ -663,71 +663,6 @@ class Definitions {

def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1

// ----- LambdaXYZ traits ------------------------------------------

private var myLambdaTraits: Set[Symbol] = Set()

/** The set of HigherKindedXYZ traits encountered so far */
def lambdaTraits: Set[Symbol] = myLambdaTraits

private var LambdaTraitForVariances = mutable.Map[List[Int], ClassSymbol]()

/** The HigherKinded trait corresponding to symbols `boundSyms` (which are assumed
* to be the type parameters of a higher-kided type). This is a class symbol that
* would be generated by the following schema.
*
* trait LambdaXYZ extends Object with P1 with ... with Pn {
* type v_1 hk$0; ...; type v_N hk$N;
* type +$Apply
* }
*
* Here:
*
* - v_i are the variances of the bound symbols (i.e. +, -, or empty).
* - XYZ is a string of length N with one letter for each variant of a bound symbol,
* using `P` (positive variance), `N` (negative variance), `I` (invariant).
* - for each positive or negative variance v_i there is a parent trait Pj which
* is the same as LambdaXYZ except that it has `I` in i-th position.
*/
def LambdaTrait(vcs: List[Int]): ClassSymbol = {
assert(vcs.nonEmpty)

def varianceFlags(v: Int) = v match {
case -1 => Contravariant
case 0 => EmptyFlags
case 1 => Covariant
}

val completer = new LazyType {
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
val cls = denot.asClass.classSymbol
val paramDecls = newScope
for (i <- 0 until vcs.length)
newTypeParam(cls, tpnme.hkArg(i), varianceFlags(vcs(i)), paramDecls)
newTypeField(cls, tpnme.hkApply, Covariant, paramDecls)
val parentTraitRefs =
for (i <- 0 until vcs.length if vcs(i) != 0)
yield LambdaTrait(vcs.updated(i, 0)).typeRef
denot.info = ClassInfo(
ScalaPackageClass.thisType, cls, ObjectClass.typeRef :: parentTraitRefs.toList, paramDecls)
}
}

val traitName = tpnme.hkLambda(vcs)

def createTrait = {
val cls = newClassSymbol(
ScalaPackageClass,
traitName,
PureInterfaceCreationFlags | Synthetic,
completer)
myLambdaTraits += cls
cls
}

LambdaTraitForVariances.getOrElseUpdate(vcs, createTrait)
}

// ----- primitive value class machinery ------------------------------------------

/** This class would also be obviated by the implicit function type design */
Expand Down
13 changes: 11 additions & 2 deletions src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ object Denotations {
/** Is this denotation different from NoDenotation or an ErrorDenotation? */
def exists: Boolean = true

/** A denotation with the info of this denotation transformed using `f` */
def mapInfo(f: Type => Type)(implicit ctx: Context): Denotation

/** If this denotation does not exist, fallback to alternative */
final def orElse(that: => Denotation) = if (this.exists) this else that

Expand Down Expand Up @@ -242,7 +245,7 @@ object Denotations {
}
else if (exists && !qualifies(symbol)) NoDenotation
else asSingleDenotation
}
}

/** Form a denotation by conjoining with denotation `that`.
*
Expand Down Expand Up @@ -456,6 +459,8 @@ object Denotations {
else if (!d2.exists) d1
else derivedMultiDenotation(d1, d2)
}
def mapInfo(f: Type => Type)(implicit ctx: Context): Denotation =
derivedMultiDenotation(denot1.mapInfo(f), denot2.mapInfo(f))
def derivedMultiDenotation(d1: Denotation, d2: Denotation) =
if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2)
override def toString = alternatives.mkString(" <and> ")
Expand Down Expand Up @@ -488,6 +493,9 @@ object Denotations {
if ((symbol eq this.symbol) && (info eq this.info)) this
else newLikeThis(symbol, info)

def mapInfo(f: Type => Type)(implicit ctx: Context): SingleDenotation =
derivedSingleDenotation(symbol, f(info))

def orElse(that: => SingleDenotation) = if (this.exists) this else that

def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
Expand Down Expand Up @@ -593,7 +601,8 @@ object Denotations {
*/
private def bringForward()(implicit ctx: Context): SingleDenotation = this match {
case denot: SymDenotation if ctx.stillValid(denot) =>
assert(ctx.runId > validFor.runId, s"denotation $denot invalid in run ${ctx.runId}. ValidFor: $validFor")
assert(ctx.runId > validFor.runId || ctx.settings.YtestPickler.value, // mixing test pickler with debug printing can travel back in time
s"denotation $denot invalid in run ${ctx.runId}. ValidFor: $validFor")
var d: SingleDenotation = denot
do {
d.validFor = Period(ctx.period.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId)
Expand Down
3 changes: 2 additions & 1 deletion src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,8 @@ object Flags {

/** Flags representing modifiers that can appear in trees */
final val ModifierFlags =
SourceModifierFlags | Module | Param | Synthetic | Package | Local | commonFlags(Mutable)
SourceModifierFlags | Module | Param | Synthetic | Package | Local |
commonFlags(Mutable)
// | Trait is subsumed by commonFlags(Lazy) from SourceModifierFlags

assert(ModifierFlags.isTermFlags && ModifierFlags.isTypeFlags)
Expand Down
23 changes: 0 additions & 23 deletions src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,29 +100,6 @@ object NameOps {
name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.head)
}

/** Is this the name of a higher-kinded type parameter of a Lambda? */
def isHkArgName =
name.length > 0 &&
name.head == tpnme.hkArgPrefixHead &&
name.startsWith(tpnme.hkArgPrefix) && {
val digits = name.drop(tpnme.hkArgPrefixLength)
digits.length <= 4 && digits.forall(_.isDigit)
}

/** The index of the higher-kinded type parameter with this name.
* Pre: isLambdaArgName.
*/
def hkArgIndex: Int =
name.drop(tpnme.hkArgPrefixLength).toString.toInt

def isLambdaTraitName(implicit ctx: Context): Boolean =
name.isTypeName && name.startsWith(tpnme.hkLambdaPrefix)

def lambdaTraitVariances(implicit ctx: Context): List[Int] = {
val vs = name.drop(tpnme.hkLambdaPrefix.length)
vs.toList.map(c => tpnme.varianceSuffixes.indexOf(c) - 1)
}

/** If the name ends with $nn where nn are
* all digits, strip the $ and the digits.
* Otherwise return the argument.
Expand Down
Loading