Skip to content

Refactor lambda types #2121

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

Merged
merged 35 commits into from
Apr 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6545606
Encode variances in parameter names
odersky Mar 14, 2017
3ff3b3a
Add neg test for illegal parameter names
odersky Mar 14, 2017
53d5311
Fix dottydoc parameter printing
odersky Mar 14, 2017
bf2f77e
Don't let illegal parameter names propagate into types
odersky Mar 14, 2017
549bd81
Drop name checking scheme for type parameters
odersky Mar 15, 2017
c024a60
Break out functionality from MethodType
odersky Mar 16, 2017
31ab880
Harmonize paramTypes and paramBounds
odersky Mar 16, 2017
5811755
ParamType refactorings
odersky Mar 16, 2017
e6abcfc
Get rid of Name parameter for LambdaType and ParamRef
odersky Mar 16, 2017
71daa03
Disable -strict when compiling dotty.
odersky Mar 17, 2017
c771851
Remove parameter from lambda type
odersky Mar 17, 2017
30af0b5
Disable -strict when compiling dotty.
odersky Mar 17, 2017
2b5d1a8
Refactor ParamRef so that no type params are needed
odersky Mar 17, 2017
70b3b90
Rename PolyParam --> TypeParamRef
odersky Mar 17, 2017
78e6cc7
Make PolyTypes subtypes of LambdaTypes
odersky Mar 17, 2017
ec4282d
Add StarLambda, HKLambda abstractions ...
odersky Mar 17, 2017
700e7ac
replace derived{Method,Poly}Type with derivedLambdaType
odersky Mar 17, 2017
5fe6f54
Eliminate ParamType
odersky Mar 17, 2017
4bfc173
Eliminate MethodOrPoly
odersky Mar 17, 2017
d0823ef
Add HKTypeLambda
odersky Mar 17, 2017
26497bb
Rename PolyTypeTree -> LambdaTypeTree
odersky Mar 17, 2017
db4f7a1
Further refactorings
odersky Mar 18, 2017
c672175
Eliminate LambdaAbstract
odersky Mar 18, 2017
e4d4999
Handle hk lambdas in tasty
odersky Mar 18, 2017
8b1340b
Generalize comparisons from PolyTypes to TypeLambdas
odersky Mar 18, 2017
f6c61f3
Split HKTypeLambda from PolyType
odersky Mar 18, 2017
1531755
Make PolyType a ground type
odersky Mar 19, 2017
8d33ca7
Merge MethodType and PolyType functionality where possible
odersky Mar 19, 2017
15e60e8
Narrow matches from TypeLambda to HKTypeLambda where appropriate
odersky Mar 19, 2017
cdc91e2
Refactorings for efficiency
odersky Mar 19, 2017
a15b14f
Fix dotty-doc to take account of refactorings
odersky Mar 19, 2017
2e04574
Generalize PolyType to TypeLambda in dotty-doc
odersky Mar 19, 2017
d101f49
Polishings
odersky Mar 19, 2017
4939b47
Update doc comment on HkTypeLambda/PolyType
odersky Mar 20, 2017
e800987
Adapt TastyPrinter to new format
odersky Apr 6, 2017
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 compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class DottyPrimitives(ctx: Context) {
ctx.error(s"Unknown primitive method $cls.$method")
else alts foreach (s =>
addPrimitive(s,
s.info.paramTypess match {
s.info.paramInfoss match {
case List(tp :: _) if code == ADD && tp =:= ctx.definitions.StringType => CONCAT
case _ => code
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ object desugar {
case ContextBounds(tbounds, cxbounds) =>
epbuf ++= makeImplicitParameters(cxbounds, isPrimaryConstructor)
tbounds
case PolyTypeTree(tparams, body) =>
cpy.PolyTypeTree(rhs)(tparams, desugarContextBounds(body))
case LambdaTypeTree(tparams, body) =>
cpy.LambdaTypeTree(rhs)(tparams, desugarContextBounds(body))
case _ =>
rhs
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped]
case mdef: TypeDef =>
def isBounds(rhs: Tree): Boolean = rhs match {
case _: TypeBoundsTree => true
case PolyTypeTree(_, body) => isBounds(body)
case LambdaTypeTree(_, body) => isBounds(body)
case _ => false
}
mdef.rhs.isEmpty || isBounds(mdef.rhs)
Expand Down
18 changes: 9 additions & 9 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -578,9 +578,9 @@ object Trees {
}

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

/** => T */
Expand Down Expand Up @@ -833,7 +833,7 @@ object Trees {
type OrTypeTree = Trees.OrTypeTree[T]
type RefinedTypeTree = Trees.RefinedTypeTree[T]
type AppliedTypeTree = Trees.AppliedTypeTree[T]
type PolyTypeTree = Trees.PolyTypeTree[T]
type LambdaTypeTree = Trees.LambdaTypeTree[T]
type ByNameTypeTree = Trees.ByNameTypeTree[T]
type TypeBoundsTree = Trees.TypeBoundsTree[T]
type Bind = Trees.Bind[T]
Expand Down Expand Up @@ -998,9 +998,9 @@ object Trees {
case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree
case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args))
}
def PolyTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree): PolyTypeTree = tree match {
case tree: PolyTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree
case _ => finalize(tree, untpd.PolyTypeTree(tparams, body))
def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree): LambdaTypeTree = tree match {
case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree
case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body))
}
def ByNameTypeTree(tree: Tree)(result: Tree): ByNameTypeTree = tree match {
case tree: ByNameTypeTree if result eq tree.result => tree
Expand Down Expand Up @@ -1144,8 +1144,8 @@ object Trees {
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
case AppliedTypeTree(tpt, args) =>
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
case PolyTypeTree(tparams, body) =>
cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
case LambdaTypeTree(tparams, body) =>
cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body))
case ByNameTypeTree(result) =>
cpy.ByNameTypeTree(tree)(transform(result))
case TypeBoundsTree(lo, hi) =>
Expand Down Expand Up @@ -1248,7 +1248,7 @@ object Trees {
this(this(x, tpt), refinements)
case AppliedTypeTree(tpt, args) =>
this(this(x, tpt), args)
case PolyTypeTree(tparams, body) =>
case LambdaTypeTree(tparams, body) =>
implicit val ctx = localCtx
this(this(x, tparams), body)
case ByNameTypeTree(result) =>
Expand Down
14 changes: 7 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def ByNameTypeTree(result: Tree)(implicit ctx: Context): ByNameTypeTree =
ta.assignType(untpd.ByNameTypeTree(result), result)

def PolyTypeTree(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): PolyTypeTree =
ta.assignType(untpd.PolyTypeTree(tparams, body), tparams, body)
def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree =
ta.assignType(untpd.LambdaTypeTree(tparams, body), tparams, body)

def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
ta.assignType(untpd.TypeBoundsTree(lo, hi), lo, hi)
Expand Down Expand Up @@ -190,7 +190,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
val maybeImplicit = if (tp.isInstanceOf[ImplicitMethodType]) Implicit else EmptyFlags
ctx.newSymbol(sym, name, TermParam | maybeImplicit, info)
}
val params = (tp.paramNames, tp.paramTypes).zipped.map(valueParam)
val params = (tp.paramNames, tp.paramInfos).zipped.map(valueParam)
val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.termRef)))
(params :: paramss, rtp)
case tp => (Nil, tp.widenExpr)
Expand Down Expand Up @@ -221,7 +221,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
case ctpe: PolyType =>
isApplicable(ctpe.instantiate(firstParent.argTypes))
case ctpe: MethodType =>
(superArgs corresponds ctpe.paramTypes)(_.tpe <:< _)
(superArgs corresponds ctpe.paramInfos)(_.tpe <:< _)
case _ =>
false
}
Expand Down Expand Up @@ -836,7 +836,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
val selected =
if (denot.isOverloaded) {
def typeParamCount(tp: Type) = tp.widen match {
case tp: PolyType => tp.paramBounds.length
case tp: PolyType => tp.paramInfos.length
case _ => 0
}
var allAlts = denot.alternatives
Expand All @@ -859,7 +859,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def adaptLastArg(lastParam: Tree, expectedType: Type) = {
if (isAnnotConstructor && !(lastParam.tpe <:< expectedType)) {
val defn = ctx.definitions
val prefix = args.take(selected.widen.paramTypess.head.size - 1)
val prefix = args.take(selected.widen.paramInfoss.head.size - 1)
expectedType match {
case defn.ArrayOf(el) =>
lastParam.tpe match {
Expand All @@ -878,7 +878,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}

val callArgs: List[Tree] = if (args.isEmpty) Nil else {
val expectedType = selected.widen.paramTypess.head.last
val expectedType = selected.widen.paramInfoss.head.last
val lastParam = args.last
adaptLastArg(lastParam, expectedType)
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,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 PolyTypeTree(tparams: List[TypeDef], body: Tree): PolyTypeTree = new PolyTypeTree(tparams, body)
def LambdaTypeTree(tparams: List[TypeDef], body: Tree): LambdaTypeTree = new LambdaTypeTree(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 Expand Up @@ -361,7 +361,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
ValDef(nme.syntheticParamName(n), tpt, EmptyTree).withFlags(SyntheticTermParam)

def lambdaAbstract(tparams: List[TypeDef], tpt: Tree)(implicit ctx: Context) =
if (tparams.isEmpty) tpt else PolyTypeTree(tparams, tpt)
if (tparams.isEmpty) tpt else LambdaTypeTree(tparams, tpt)

/** A reference to given definition. If definition is a repeated
* parameter, the reference will be a repeated argument.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ object Config {
* accesses javac's settings.)
*
* It is recommended to turn this option on only when chasing down
* a PolyParam instantiation error. See comment in Types.TypeVar.instantiate.
* a TypeParamRef instantiation error. See comment in Types.TypeVar.instantiate.
*/
final val debugCheckConstraintsClosed = false

Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Constants.scala
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ object Constants {
def convertTo(pt: Type)(implicit ctx: Context): Constant = {
def classBound(pt: Type): Type = pt.dealias.stripTypeVar match {
case tref: TypeRef if !tref.symbol.isClass => classBound(tref.info.bounds.lo)
case param: PolyParam =>
case param: TypeParamRef =>
ctx.typerState.constraint.entry(param) match {
case TypeBounds(lo, hi) =>
if (hi.classSymbol.isPrimitiveValueClass) hi //constrain further with high bound
else classBound(lo)
case NoType => classBound(param.binder.paramBounds(param.paramNum).lo)
case NoType => classBound(param.binder.paramInfos(param.paramNum).lo)
case inst => classBound(inst)
}
case pt => pt
Expand Down
60 changes: 30 additions & 30 deletions compiler/src/dotty/tools/dotc/core/Constraint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,64 +13,64 @@ import config.Printers.constr
/** Constraint over undetermined type parameters. Constraints are built
* over values of the following types:
*
* - PolyType A constraint constrains the type parameters of a set of PolyTypes
* - PolyParam The parameters of the constrained polytypes
* - TypeVar Every constrained parameter might be associated with a TypeVar
* that has the PolyParam as origin.
* - TypeLambda A constraint constrains the type parameters of a set of TypeLambdas
* - TypeParamRef The parameters of the constrained type lambdas
* - TypeVar Every constrained parameter might be associated with a TypeVar
* that has the TypeParamRef as origin.
*/
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: TypeLambda): Boolean

/** Does the constraint's domain contain the type parameter `param`? */
def contains(param: PolyParam): Boolean
def contains(param: TypeParamRef): Boolean

/** Does this constraint contain the type variable `tvar` and is it uninstantiated? */
def contains(tvar: TypeVar): Boolean

/** The constraint entry for given type parameter `param`, or NoType if `param` is not part of
* the constraint domain. Note: Low level, implementation dependent.
*/
def entry(param: PolyParam): Type
def entry(param: TypeParamRef): Type

/** The type variable corresponding to parameter `param`, or
* NoType, if `param` is not in constrained or is not paired with a type variable.
*/
def typeVarOfParam(param: PolyParam): Type
def typeVarOfParam(param: TypeParamRef): Type

/** Is it known that `param1 <:< param2`? */
def isLess(param1: PolyParam, param2: PolyParam): Boolean
def isLess(param1: TypeParamRef, param2: TypeParamRef): Boolean

/** The parameters that are known to be smaller wrt <: than `param` */
def lower(param: PolyParam): List[PolyParam]
def lower(param: TypeParamRef): List[TypeParamRef]

/** The parameters that are known to be greater wrt <: than `param` */
def upper(param: PolyParam): List[PolyParam]
def upper(param: TypeParamRef): List[TypeParamRef]

/** lower(param) \ lower(butNot) */
def exclusiveLower(param: PolyParam, butNot: PolyParam): List[PolyParam]
def exclusiveLower(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef]

/** upper(param) \ upper(butNot) */
def exclusiveUpper(param: PolyParam, butNot: PolyParam): List[PolyParam]
def exclusiveUpper(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef]

/** The constraint bounds for given type parameter `param`.
* Poly params that are known to be smaller or greater than `param`
* are not contained in the return bounds.
* @pre `param` is not part of the constraint domain.
*/
def nonParamBounds(param: PolyParam): TypeBounds
def nonParamBounds(param: TypeParamRef): TypeBounds

/** The lower bound of `param` including all known-to-be-smaller parameters */
def fullLowerBound(param: PolyParam)(implicit ctx: Context): Type
def fullLowerBound(param: TypeParamRef)(implicit ctx: Context): Type

/** The upper bound of `param` including all known-to-be-greater parameters */
def fullUpperBound(param: PolyParam)(implicit ctx: Context): Type
def fullUpperBound(param: TypeParamRef)(implicit ctx: Context): Type

/** The bounds of `param` including all known-to-be-smaller and -greater parameters */
def fullBounds(param: PolyParam)(implicit ctx: Context): TypeBounds
def fullBounds(param: TypeParamRef)(implicit ctx: Context): TypeBounds

/** A new constraint which is derived from this constraint by adding
* entries for all type parameters of `poly`.
Expand All @@ -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: TypeLambda, 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 All @@ -90,44 +90,44 @@ abstract class Constraint extends Showable {
*
* @pre `this contains param`.
*/
def updateEntry(param: PolyParam, tp: Type)(implicit ctx: Context): This
def updateEntry(param: TypeParamRef, tp: Type)(implicit ctx: Context): This

/** A constraint that includes the relationship `p1 <: p2`.
* `<:` relationships between parameters ("edges") are propagated, but
* non-parameter bounds are left alone.
*/
def addLess(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This
def addLess(p1: TypeParamRef, p2: TypeParamRef)(implicit ctx: Context): This

/** A constraint resulting from adding p2 = p1 to this constraint, and at the same
* time transferring all bounds of p2 to p1
*/
def unify(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This
def unify(p1: TypeParamRef, p2: TypeParamRef)(implicit ctx: Context): This

/** A new constraint which is derived from this constraint by removing
* the type parameter `param` from the domain and replacing all top-level occurrences
* of the parameter elsewhere in the constraint by type `tp`, or a conservative
* approximation of it if that is needed to avoid cycles.
* Occurrences nested inside a refinement or prefix are not affected.
*/
def replace(param: PolyParam, tp: Type)(implicit ctx: Context): This
def replace(param: TypeParamRef, tp: Type)(implicit ctx: Context): This

/** Is entry associated with `pt` removable? This is the case if
* all type parameters of the entry are associated with type variables
* which have their `inst` fields set.
*/
def isRemovable(pt: PolyType): Boolean
def isRemovable(pt: TypeLambda): Boolean

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

/** The polytypes constrained by this constraint */
def domainPolys: List[PolyType]
/** The type lambdas constrained by this constraint */
def domainLambdas: List[TypeLambda]

/** The polytype parameters constrained by this constraint */
def domainParams: List[PolyParam]
/** The type lambda parameters constrained by this constraint */
def domainParams: List[TypeParamRef]

/** Check whether predicate holds for all parameters in constraint */
def forallParams(p: PolyParam => Boolean): Boolean
def forallParams(p: TypeParamRef => Boolean): Boolean

/** Perform operation `op` on all typevars, or only on uninstantiated
* typevars, depending on whether `uninstOnly` is set or not.
Expand All @@ -143,6 +143,6 @@ abstract class Constraint extends Showable {
/** Check that no constrained parameter contains itself as a bound */
def checkNonCyclic()(implicit ctx: Context): Unit

/** Check that constraint only refers to PolyParams bound by itself */
/** Check that constraint only refers to TypeParamRefs bound by itself */
def checkClosed()(implicit ctx: Context): Unit
}
Loading