From 6545606cefaf8ec7090f8a601123bfae61b441a6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 14 Mar 2017 16:47:55 +0100 Subject: Encode variances in parameter names This leads to a slight overall simplification, harmonizes pickle format with internal representation, and makes MethodTypes and PolyTypes more similar to each other. I believe the change is useful as it is, but in particular it is a useful step for an eventual unification of MethodTypes and PolyTypes. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 6 ++++ .../src/dotty/tools/dotc/core/Definitions.scala | 2 +- compiler/src/dotty/tools/dotc/core/NameOps.scala | 26 +++++++++++++++- compiler/src/dotty/tools/dotc/core/StdNames.scala | 1 - .../dotty/tools/dotc/core/TypeApplications.scala | 9 ++++-- .../src/dotty/tools/dotc/core/TypeComparer.scala | 8 ++--- compiler/src/dotty/tools/dotc/core/Types.scala | 35 ++++++++++++++-------- .../dotty/tools/dotc/core/tasty/TastyFormat.scala | 6 +--- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 4 +-- .../tools/dotc/core/tasty/TreeUnpickler.scala | 6 ++-- .../dotty/tools/dotc/printing/PlainPrinter.scala | 8 ++--- .../dotc/transform/FullParameterization.scala | 4 +-- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- 13 files changed, 76 insertions(+), 41 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 8499330fb..5f9d48798 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -242,6 +242,12 @@ object desugar { * class C { type v C$T; type v T = C$T } */ def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = { + val name = + if (tdef.name.hasVariance && tdef.mods.is(Param)) { + ctx.error(em"type parameter name may not start with `+' or `-'", tdef.pos) + ("$" + tdef.name).toTypeName + } + else tdef.name if (tdef.mods is PrivateLocalParam) { val tparam = cpy.TypeDef(tdef)(name = tdef.name.expandedName(ctx.owner)) .withMods(tdef.mods &~ PrivateLocal | ExpandedName) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 39b46cbfe..c48016b67 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -152,7 +152,7 @@ class Definitions { resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = { val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount) val tparamBounds = tparamNames map (_ => TypeBounds.empty) - val ptype = PolyType(tparamNames, tparamNames.map(alwaysZero))(_ => tparamBounds, resultTypeFn) + val ptype = PolyType(tparamNames)(_ => tparamBounds, resultTypeFn) enterMethod(cls, name, ptype, flags) } diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index ea905c19f..240ad359b 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -196,6 +196,31 @@ object NameOps { if (name.isModuleClassName) name.stripModuleClassSuffix.freshened.moduleClassName else likeTyped(ctx.freshName(name ++ NameTransformer.NAME_JOIN_STRING))) + /** Name with variance prefix: `+` for covariant, `-` for contravariant */ + def withVariance(v: Int): N = + if (hasVariance) dropVariance.withVariance(v) + else v match { + case -1 => likeTyped('-' +: name) + case 1 => likeTyped('+' +: name) + case 0 => name + } + + /** Does name have a `+`/`-` variance prefix? */ + def hasVariance: Boolean = + name.nonEmpty && name.head == '+' || name.head == '-' + + /** Drop variance prefix if name has one */ + def dropVariance: N = if (hasVariance) likeTyped(name.tail) else name + + /** The variance as implied by the variance prefix, or 0 if there is + * no variance prefix. + */ + def variance = name.head match { + case '-' => -1 + case '+' => 1 + case _ => 0 + } + /** Translate a name into a list of simple TypeNames and TermNames. * In all segments before the last, type/term is determined by whether * the following separator char is '.' or '#'. The last segment @@ -271,7 +296,6 @@ object NameOps { else -1 } - /** The number of hops specified in an outer-select name */ def outerSelectHops: Int = { require(isOuterSelect) diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index bc3f96d91..30fa03537 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -850,5 +850,4 @@ object StdNames { val tpnme = new ScalaTypeNames val jnme = new JavaTermNames val jtpnme = new JavaTypeNames - } diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index ba3e6a461..a7ce1ee85 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -278,9 +278,10 @@ class TypeApplications(val self: Type) extends AnyVal { * TODO: Handle parameterized lower bounds */ def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = { + def nameWithVariance(tparam: TypeParamInfo) = + tparam.paramName.withVariance(tparam.paramVariance) def expand(tp: Type) = - PolyType( - tparams.map(_.paramName), tparams.map(_.paramVariance))( + PolyType(tparams.map(nameWithVariance))( tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds), tl => tl.lifted(tparams, tp)) if (tparams.isEmpty) self @@ -365,7 +366,9 @@ class TypeApplications(val self: Type) extends AnyVal { case arg @ PolyType(tparams, body) if !tparams.corresponds(hkParams)(_.paramVariance == _.paramVariance) && tparams.corresponds(hkParams)(varianceConforms) => - PolyType(tparams.map(_.paramName), hkParams.map(_.paramVariance))( + PolyType( + (tparams, hkParams).zipped.map((tparam, hkparam) => + tparam.paramName.withVariance(hkparam.paramVariance)))( tl => arg.paramBounds.map(_.subst(arg, tl).bounds), tl => arg.resultType.subst(arg, tl) ) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 57dde3288..a8f92522c 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -669,7 +669,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val tparams1 = tparams1a.drop(lengthDiff) variancesConform(tparams1, tparams) && { if (lengthDiff > 0) - tycon1b = PolyType(tparams1.map(_.paramName), tparams1.map(_.paramVariance))( + tycon1b = PolyType(tparams1.map(_.paramName))( tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds), tl => tycon1a.appliedTo(args1.take(lengthDiff) ++ tparams1.indices.toList.map(PolyParam(tl, _)))) @@ -1281,9 +1281,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { original(tp1.appliedTo(tp1.typeParams.map(_.paramBoundsAsSeenFrom(tp1))), tp2) else PolyType( - paramNames = tpnme.syntheticTypeParamNames(tparams1.length), - variances = (tparams1, tparams2).zipped.map((tparam1, tparam2) => - (tparam1.paramVariance + tparam2.paramVariance) / 2))( + paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2) + .zipped.map((pname, tparam1, tparam2) => + pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))( paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => tl.lifted(tparams1, tparam1.paramBoundsAsSeenFrom(tp1)).bounds & tl.lifted(tparams2, tparam2.paramBoundsAsSeenFrom(tp2)).bounds), diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index c80107f93..6b5be5489 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2572,8 +2572,20 @@ object Types { } } - /** A type lambda of the form `[v_0 X_0, ..., v_n X_n] => T` */ - class PolyType(val paramNames: List[TypeName], val variances: List[Int])( + /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T` + * This is used both as a type of a polymorphic method and as a type of + * a higher-kidned type parameter. Variances are encoded in parameter + * names. A name starting with `+` designates a covariant parameter, + * a name starting with `-` designates a contravariant parameter, + * and every other name designates a non-variant parameter. + * + * @param paramNames The names `X_0`, ..., `X_n` + * @param paramBoundsExp A function that, given the polytype itself, returns the + * parameter bounds `B_1`, ..., `B_n` + * @param resultTypeExp A function that, given the polytype itself, returns the + * result type `T`. + */ + class PolyType(val paramNames: List[TypeName])( paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) extends CachedProxyType with BindingType with MethodOrPoly { @@ -2611,7 +2623,7 @@ object Types { paramBounds.mapConserve(_.substParams(this, argTypes).bounds) def newLikeThis(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType = - PolyType.apply(paramNames, variances)( + PolyType.apply(paramNames)( x => paramBounds mapConserve (_.subst(this, x).bounds), x => resType.subst(this, x)) @@ -2644,7 +2656,7 @@ object Types { case t => mapOver(t) } } - PolyType(paramNames ++ that.paramNames, variances ++ that.variances)( + PolyType(paramNames ++ that.paramNames)( x => this.paramBounds.mapConserve(_.subst(this, x).bounds) ++ that.paramBounds.mapConserve(shift(_).subst(that, x).bounds), x => shift(that.resultType).subst(that, x).subst(this, x)) @@ -2664,28 +2676,27 @@ object Types { case other: PolyType => other.paramNames == this.paramNames && other.paramBounds == this.paramBounds && - other.resType == this.resType && - other.variances == this.variances + other.resType == this.resType case _ => false } - override def toString = s"PolyType($variances, $paramNames, $paramBounds, $resType)" + override def toString = s"PolyType($paramNames, $paramBounds, $resType)" - override def computeHash = doHash(variances ::: paramNames, resType, paramBounds) + override def computeHash = doHash(paramNames, resType, paramBounds) } object PolyType { - def apply(paramNames: List[TypeName], variances: List[Int])( + def apply(paramNames: List[TypeName])( paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = { - unique(new PolyType(paramNames, variances)(paramBoundsExp, resultTypeExp)) + unique(new PolyType(paramNames)(paramBoundsExp, resultTypeExp)) } def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] = Some((tl.typeParams, tl.resType)) def any(n: Int)(implicit ctx: Context) = - apply(tpnme.syntheticTypeParamNames(n), List.fill(n)(0))( + apply(tpnme.syntheticTypeParamNames(n))( pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) } @@ -2698,7 +2709,7 @@ object Types { def paramBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n) def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = paramBounds def paramBoundsOrCompleter(implicit ctx: Context): Type = paramBounds - def paramVariance(implicit ctx: Context): Int = tl.variances(n) + def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance def toArg: Type = PolyParam(tl, n) def paramRef(implicit ctx: Context): Type = PolyParam(tl, n) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index cb1b56c3c..98577f3c5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -151,7 +151,7 @@ Standard-Section: "ASTs" TopLevelStat* BIND Length boundName_NameRef bounds_Type // for type-variables defined in a type pattern BYNAMEtype underlying_Type - POLYtype Length result_Type NamesTypes // variance encoded in front of name: +/-/= + POLYtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing) METHODtype Length result_Type NamesTypes // needed for refinements PARAMtype Length binder_ASTref paramNum_Nat // needed for refinements SHARED type_ASTRef @@ -546,8 +546,4 @@ object TastyFormat { case POLYtype | METHODtype => -1 case _ => 0 } - - /** Map between variances and name prefixes */ - val varianceToPrefix = Map(-1 -> '-', 0 -> '=', 1 -> '+') - val prefixToVariance = Map('-' -> -1, '=' -> 0, '+' -> 1) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 80270aa25..871f39838 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -255,9 +255,7 @@ class TreePickler(pickler: TastyPickler) { pickleType(tpe.underlying) case tpe: PolyType => writeByte(POLYtype) - val paramNames = tpe.typeParams.map(tparam => - varianceToPrefix(tparam.paramVariance) +: tparam.paramName) - pickleMethodic(tpe.resultType, paramNames, tpe.paramBounds) + pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramBounds) case tpe: MethodType if richTypes => writeByte(METHODtype) pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramTypes) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 88b6eef7a..6c6ebc0a3 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -268,10 +268,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle registerSym(start, sym) TypeRef.withFixedSym(NoPrefix, sym.name, sym) case POLYtype => - val (rawNames, paramReader) = readNamesSkipParams - val (variances, paramNames) = rawNames - .map(name => (prefixToVariance(name.head), name.tail.toTypeName)).unzip - val result = PolyType(paramNames, variances)( + val (paramNames, paramReader) = readNamesSkipParams + val result = PolyType(paramNames.map(_.toTypeName))( pt => registeringType(pt, paramReader.readParamTypes[TypeBounds](end)), pt => readType()) goto(end) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 67d44daa1..ba5592bd6 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -176,10 +176,9 @@ class PlainPrinter(_ctx: Context) extends Printer { case tp: ExprType => changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) } case tp: PolyType => - def paramText(variance: Int, name: Name, bounds: TypeBounds): Text = - varianceString(variance) ~ name.toString ~ toText(bounds) + def paramText(name: Name, bounds: TypeBounds): Text = name.toString ~ toText(bounds) changePrec(GlobalPrec) { - "[" ~ Text((tp.variances, tp.paramNames, tp.paramBounds).zipped.map(paramText), ", ") ~ + "[" ~ Text((tp.paramNames, tp.paramBounds).zipped.map(paramText), ", ") ~ "]" ~ (" => " provided !tp.resultType.isInstanceOf[MethodType]) ~ toTextGlobal(tp.resultType) } @@ -209,7 +208,8 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def polyParamNameString(name: TypeName): String = name.toString - protected def polyParamNameString(param: PolyParam): String = polyParamNameString(param.binder.paramNames(param.paramNum)) + protected def polyParamNameString(param: PolyParam): String = + polyParamNameString(param.binder.paramNames(param.paramNum)) /** The name of the symbol without a unique id. Under refined printing, * the decoded original name. diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index 0cb453b4c..cdc28b23f 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -122,14 +122,14 @@ trait FullParameterization { info match { case info: PolyType => - PolyType(info.paramNames ++ ctnames, info.variances ++ ctvariances)( + PolyType(info.paramNames ++ ctnames)( pt => (info.paramBounds.map(mapClassParams(_, pt).bounds) ++ mappedClassBounds(pt)).mapConserve(_.subst(info, pt).bounds), pt => resultType(mapClassParams(_, pt)).subst(info, pt)) case _ => if (ctparams.isEmpty) resultType(identity) - else PolyType(ctnames, ctvariances)(mappedClassBounds, pt => resultType(mapClassParams(_, pt))) + else PolyType(ctnames)(mappedClassBounds, pt => resultType(mapClassParams(_, pt))) } } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index f96b8ae1d..d61e24261 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -401,7 +401,7 @@ object ProtoTypes { /** Create a new polyparam that represents a dependent method parameter singleton */ def newDepPolyParam(tp: Type)(implicit ctx: Context): PolyParam = { - val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil, 0 :: Nil)( + val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil)( pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil, pt => defn.AnyType) ctx.typeComparer.addToConstraint(poly, Nil) -- cgit v1.2.3 From 3ff3b3adb9af8a8860f2c10f1f8620cd988c8e8e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 14 Mar 2017 17:26:58 +0100 Subject: Add neg test for illegal parameter names and fix typo --- compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- tests/neg/illegal-param-names.scala | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 tests/neg/illegal-param-names.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 6b5be5489..533a8f3f6 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2574,7 +2574,7 @@ object Types { /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T` * This is used both as a type of a polymorphic method and as a type of - * a higher-kidned type parameter. Variances are encoded in parameter + * a higher-kinded type parameter. Variances are encoded in parameter * names. A name starting with `+` designates a covariant parameter, * a name starting with `-` designates a contravariant parameter, * and every other name designates a non-variant parameter. diff --git a/tests/neg/illegal-param-names.scala b/tests/neg/illegal-param-names.scala new file mode 100644 index 000000000..9ca06798a --- /dev/null +++ b/tests/neg/illegal-param-names.scala @@ -0,0 +1 @@ +class Test[++, --] // error // error -- cgit v1.2.3 From 53d5311f59689f73f2713bf5b704d6def8b2884e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 14 Mar 2017 17:36:00 +0100 Subject: Fix dottydoc parameter printing --- doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala index cfb66fa56..ad8981ea2 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala @@ -94,10 +94,7 @@ class DocASTPhase extends Phase { NonEntity else { val tparams = t.rhs.tpe match { - case tp: PolyType => tp.paramRefs.zip(tp.variances).map { case (tp, variance) => - val varianceSym = if (variance == 1) "+" else if (variance == -1) "-" else "" - varianceSym + tp.paramName.show - } + case tp: PolyType => tp.paramNames.map(_.show) case _ => Nil } TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe), tparams) -- cgit v1.2.3 From bf2f77e112bbc1d242a4f91b113ba3cc14c3dcc8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 14 Mar 2017 17:49:32 +0100 Subject: Don't let illegal parameter names propagate into types --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 5f9d48798..1531e67b3 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -242,20 +242,20 @@ object desugar { * class C { type v C$T; type v T = C$T } */ def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = { - val name = + val checkedName = if (tdef.name.hasVariance && tdef.mods.is(Param)) { ctx.error(em"type parameter name may not start with `+' or `-'", tdef.pos) ("$" + tdef.name).toTypeName } else tdef.name if (tdef.mods is PrivateLocalParam) { - val tparam = cpy.TypeDef(tdef)(name = tdef.name.expandedName(ctx.owner)) + val tparam = cpy.TypeDef(tdef)(name = checkedName.expandedName(ctx.owner)) .withMods(tdef.mods &~ PrivateLocal | ExpandedName) - val alias = cpy.TypeDef(tdef)(rhs = refOfDef(tparam)) + val alias = cpy.TypeDef(tdef)(name = checkedName, rhs = refOfDef(tparam)) .withMods(tdef.mods & VarianceFlags | PrivateLocalParamAccessor | Synthetic) Thicket(tparam, alias) } - else tdef + else cpy.TypeDef(tdef)(name = checkedName) } @sharable private val synthetic = Modifiers(Synthetic) -- cgit v1.2.3 From 549bd812684e6f269610234ddefe8054dfb42746 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 15 Mar 2017 11:13:37 +0100 Subject: Drop name checking scheme for type parameters It was a red herring. Symbolic names are expanded anyway to $plus / $minus, so they can't be confused with a variance prefix. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 12 +++--------- tests/neg/illegal-param-names.scala | 1 - 2 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 tests/neg/illegal-param-names.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 1531e67b3..10b522eaa 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -242,20 +242,14 @@ object desugar { * class C { type v C$T; type v T = C$T } */ def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = { - val checkedName = - if (tdef.name.hasVariance && tdef.mods.is(Param)) { - ctx.error(em"type parameter name may not start with `+' or `-'", tdef.pos) - ("$" + tdef.name).toTypeName - } - else tdef.name if (tdef.mods is PrivateLocalParam) { - val tparam = cpy.TypeDef(tdef)(name = checkedName.expandedName(ctx.owner)) + val tparam = cpy.TypeDef(tdef)(name = tdef.name.expandedName(ctx.owner)) .withMods(tdef.mods &~ PrivateLocal | ExpandedName) - val alias = cpy.TypeDef(tdef)(name = checkedName, rhs = refOfDef(tparam)) + val alias = cpy.TypeDef(tdef)(name = tdef.name, rhs = refOfDef(tparam)) .withMods(tdef.mods & VarianceFlags | PrivateLocalParamAccessor | Synthetic) Thicket(tparam, alias) } - else cpy.TypeDef(tdef)(name = checkedName) + else tdef } @sharable private val synthetic = Modifiers(Synthetic) diff --git a/tests/neg/illegal-param-names.scala b/tests/neg/illegal-param-names.scala deleted file mode 100644 index 9ca06798a..000000000 --- a/tests/neg/illegal-param-names.scala +++ /dev/null @@ -1 +0,0 @@ -class Test[++, --] // error // error -- cgit v1.2.3 From c024a6037f3dd7e7458d936566cd4b653b8b7545 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 16 Mar 2017 15:15:28 +0100 Subject: Break out functionality from MethodType and generalize MethodParam to ParamRef, and TypeParamInfo to ParamInfo --- compiler/src/dotty/tools/dotc/core/ParamInfo.scala | 40 ++++ compiler/src/dotty/tools/dotc/core/Symbols.scala | 10 +- .../dotty/tools/dotc/core/TypeApplications.scala | 24 +-- .../src/dotty/tools/dotc/core/TypeComparer.scala | 16 +- .../src/dotty/tools/dotc/core/TypeParamInfo.scala | 40 ---- compiler/src/dotty/tools/dotc/core/Types.scala | 206 +++++++++++++-------- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- .../dotty/tools/dotc/printing/PlainPrinter.scala | 6 +- .../tools/dotc/reporting/diagnostic/messages.scala | 4 +- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 4 +- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 2 +- .../dotc/transform/FullParameterization.scala | 2 +- .../tools/dotc/transform/SuperAccessors.scala | 4 +- .../src/dotty/tools/dotc/typer/Applications.scala | 4 +- compiler/src/dotty/tools/dotc/typer/Checking.scala | 4 +- .../dotty/tools/dotc/typer/ErrorReporting.scala | 2 +- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 +- .../src/dotty/tools/dotc/typer/Variances.scala | 2 +- 21 files changed, 212 insertions(+), 170 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/core/ParamInfo.scala delete mode 100644 compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala diff --git a/compiler/src/dotty/tools/dotc/core/ParamInfo.scala b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala new file mode 100644 index 000000000..efae24916 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala @@ -0,0 +1,40 @@ +package dotty.tools.dotc.core + +import Names.TypeName +import Contexts.Context +import Types.{Type, TypeBounds} + +/** A common super trait of Symbol and LambdaParam. + * Used to capture the attributes of type parameters which can be implemented as either. + */ +trait ParamInfo { + + /** Is this the info of a type parameter? Will return `false` for symbols + * that are not type parameters. + */ + def isTypeParam(implicit ctx: Context): Boolean + + /** The name of the type parameter */ + def paramName(implicit ctx: Context): TypeName + + /** The info of the type parameter */ + def paramInfo(implicit ctx: Context): Type + + /** The info of the type parameter as seen from a prefix type. + * For type parameter symbols, this is the `memberInfo` as seen from `prefix`. + * For type lambda parameters, it's the same as `paramBounds` as + * `asSeenFrom` has already been applied to the whole type lambda. + */ + def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type + + /** The parameter bounds, or the completer if the type parameter + * is an as-yet uncompleted symbol. + */ + def paramInfoOrCompleter(implicit ctx: Context): Type + + /** The variance of the type parameter */ + def paramVariance(implicit ctx: Context): Int + + /** A type that refers to the parameter */ + def paramRef(implicit ctx: Context): Type +} \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 33aba4d13..705b2c133 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -384,7 +384,7 @@ object Symbols { * @param coord The coordinates of the symbol (a position or an index) * @param id A unique identifier of the symbol (unique per ContextBase) */ - class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with TypeParamInfo with printing.Showable { + class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with ParamInfo with printing.Showable { type ThisName <: Name @@ -513,12 +513,12 @@ object Symbols { */ def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition - // TypeParamInfo methods + // ParamInfo methods def isTypeParam(implicit ctx: Context) = denot.is(TypeParam) def paramName(implicit ctx: Context) = name.asTypeName - def paramBounds(implicit ctx: Context) = denot.info.bounds - def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds - def paramBoundsOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter + def paramInfo(implicit ctx: Context) = denot.info.bounds + def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this) + def paramInfoOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter def paramVariance(implicit ctx: Context) = denot.variance def paramRef(implicit ctx: Context) = denot.typeRef diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index a7ce1ee85..9a1a3359e 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -47,14 +47,14 @@ object TypeApplications { /** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`? */ - def varianceConforms(tparam1: TypeParamInfo, tparam2: TypeParamInfo)(implicit ctx: Context): Boolean = + def varianceConforms(tparam1: ParamInfo, tparam2: ParamInfo)(implicit ctx: Context): Boolean = varianceConforms(tparam1.paramVariance, tparam2.paramVariance) /** Do the variances of type parameters `tparams1` conform to the variances * of corresponding type parameters `tparams2`? * This is only the case of `tparams1` and `tparams2` have the same length. */ - def variancesConform(tparams1: List[TypeParamInfo], tparams2: List[TypeParamInfo])(implicit ctx: Context): Boolean = + def variancesConform(tparams1: List[ParamInfo], tparams2: List[ParamInfo])(implicit ctx: Context): Boolean = tparams1.corresponds(tparams2)(varianceConforms) /** Extractor for @@ -96,7 +96,7 @@ object TypeApplications { refinements = rt :: refinements tycon = rt.parent.stripTypeVar } - def collectArgs(tparams: List[TypeParamInfo], + def collectArgs(tparams: List[ParamInfo], refinements: List[RefinedType], argBuf: mutable.ListBuffer[Type]): Option[(Type, List[Type])] = refinements match { case Nil if tparams.isEmpty && argBuf.nonEmpty => @@ -117,9 +117,9 @@ object TypeApplications { /** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK */ - def EtaExpandIfHK(tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): List[Type] = + def EtaExpandIfHK(tparams: List[ParamInfo], args: List[Type])(implicit ctx: Context): List[Type] = if (tparams.isEmpty) args - else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramBoundsOrCompleter)) + else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramInfoOrCompleter)) /** A type map that tries to reduce (part of) the result type of the type lambda `tycon` * with the given `args`(some of which are wildcard arguments represented by type bounds). @@ -209,7 +209,7 @@ class TypeApplications(val self: Type) extends AnyVal { * with the bounds on its hk args. See `LambdaAbstract`, where these * types get introduced, and see `isBoundedLambda` below for the test. */ - final def typeParams(implicit ctx: Context): List[TypeParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ { + final def typeParams(implicit ctx: Context): List[ParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ { self match { case self: ClassInfo => self.cls.typeParams @@ -236,7 +236,7 @@ class TypeApplications(val self: Type) extends AnyVal { } /** If `self` is a higher-kinded type, its type parameters, otherwise Nil */ - final def hkTypeParams(implicit ctx: Context): List[TypeParamInfo] = + final def hkTypeParams(implicit ctx: Context): List[ParamInfo] = if (isHK) typeParams else Nil /** If `self` is a generic class, its type parameter symbols, otherwise Nil */ @@ -277,12 +277,12 @@ class TypeApplications(val self: Type) extends AnyVal { * * TODO: Handle parameterized lower bounds */ - def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = { - def nameWithVariance(tparam: TypeParamInfo) = + def LambdaAbstract(tparams: List[ParamInfo])(implicit ctx: Context): Type = { + def nameWithVariance(tparam: ParamInfo) = tparam.paramName.withVariance(tparam.paramVariance) def expand(tp: Type) = PolyType(tparams.map(nameWithVariance))( - tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds), + tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds), tl => tl.lifted(tparams, tp)) if (tparams.isEmpty) self else self match { @@ -393,7 +393,7 @@ class TypeApplications(val self: Type) extends AnyVal { */ final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ { val typParams = self.typeParams - def matchParams(t: Type, tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): Type = args match { + def matchParams(t: Type, tparams: List[ParamInfo], args: List[Type])(implicit ctx: Context): Type = args match { case arg :: args1 => try { val tparam :: tparams1 = tparams @@ -478,7 +478,7 @@ class TypeApplications(val self: Type) extends AnyVal { /** Turn this type, which is used as an argument for * type parameter `tparam`, into a TypeBounds RHS */ - final def toBounds(tparam: TypeParamInfo)(implicit ctx: Context): TypeBounds = self match { + final def toBounds(tparam: ParamInfo)(implicit ctx: Context): TypeBounds = self match { case self: TypeBounds => // this can happen for wildcard args self case _ => diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index a8f92522c..fb16a6772 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -447,7 +447,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def boundsOK = ctx.scala2Mode || tparams1.corresponds(tparams2)((tparam1, tparam2) => - isSubType(tparam2.paramBounds.subst(tp2, tp1), tparam1.paramBounds)) + isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo)) val saved = comparedPolyTypes comparedPolyTypes += tp1 comparedPolyTypes += tp2 @@ -670,7 +670,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { variancesConform(tparams1, tparams) && { if (lengthDiff > 0) tycon1b = PolyType(tparams1.map(_.paramName))( - tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds), + tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds), tl => tycon1a.appliedTo(args1.take(lengthDiff) ++ tparams1.indices.toList.map(PolyParam(tl, _)))) (ctx.mode.is(Mode.TypevarsMissContext) || @@ -764,7 +764,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Subtype test for corresponding arguments in `args1`, `args2` according to * variances in type parameters `tparams`. */ - def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[TypeParamInfo]): Boolean = + def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[ParamInfo]): Boolean = if (args1.isEmpty) args2.isEmpty else args2.nonEmpty && { val v = tparams.head.paramVariance @@ -783,7 +783,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * - the type parameters of `B` match one-by-one the variances of `tparams`, * - `B` satisfies predicate `p`. */ - private def testLifted(tp1: Type, tp2: Type, tparams: List[TypeParamInfo], p: Type => Boolean): Boolean = { + private def testLifted(tp1: Type, tp2: Type, tparams: List[ParamInfo], p: Type => Boolean): Boolean = { val classBounds = tp2.classSymbols def recur(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => @@ -1276,17 +1276,17 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val tparams2 = tp2.typeParams if (tparams1.isEmpty) if (tparams2.isEmpty) op(tp1, tp2) - else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramBoundsAsSeenFrom(tp2)))) + else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramInfoAsSeenFrom(tp2)))) else if (tparams2.isEmpty) - original(tp1.appliedTo(tp1.typeParams.map(_.paramBoundsAsSeenFrom(tp1))), tp2) + original(tp1.appliedTo(tp1.typeParams.map(_.paramInfoAsSeenFrom(tp1))), tp2) else PolyType( paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2) .zipped.map((pname, tparam1, tparam2) => pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))( paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => - tl.lifted(tparams1, tparam1.paramBoundsAsSeenFrom(tp1)).bounds & - tl.lifted(tparams2, tparam2.paramBoundsAsSeenFrom(tp2)).bounds), + tl.lifted(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds & + tl.lifted(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds), resultTypeExp = tl => original(tl.lifted(tparams1, tp1).appliedTo(tl.paramRefs), tl.lifted(tparams2, tp2).appliedTo(tl.paramRefs))) diff --git a/compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala b/compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala deleted file mode 100644 index 647c895db..000000000 --- a/compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala +++ /dev/null @@ -1,40 +0,0 @@ -package dotty.tools.dotc.core - -import Names.TypeName -import Contexts.Context -import Types.{Type, TypeBounds} - -/** A common super trait of Symbol and LambdaParam. - * Used to capture the attributes of type parameters which can be implemented as either. - */ -trait TypeParamInfo { - - /** Is this the info of a type parameter? Will return `false` for symbols - * that are not type parameters. - */ - def isTypeParam(implicit ctx: Context): Boolean - - /** The name of the type parameter */ - def paramName(implicit ctx: Context): TypeName - - /** The info of the type parameter */ - def paramBounds(implicit ctx: Context): TypeBounds - - /** The info of the type parameter as seen from a prefix type. - * For type parameter symbols, this is the `memberInfo` as seen from `prefix`. - * For type lambda parameters, it's the same as `paramBounds` as - * `asSeenFrom` has already been applied to the whole type lambda. - */ - def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds - - /** The parameter bounds, or the completer if the type parameter - * is an as-yet uncompleted symbol. - */ - def paramBoundsOrCompleter(implicit ctx: Context): Type - - /** The variance of the type parameter */ - def paramVariance(implicit ctx: Context): Int - - /** A type that refers to the parameter */ - def paramRef(implicit ctx: Context): Type -} \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 533a8f3f6..17879f168 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -54,7 +54,7 @@ object Types { * | | +--- ThisType * | | +--- SuperType * | | +--- ConstantType - * | | +--- MethodParam + * | | +--- TermParamRef * | | +----RecThis * | | +--- SkolemType * | +- PolyParam @@ -2317,18 +2317,52 @@ object Types { trait MethodOrPoly extends MethodicType - abstract case class MethodType(paramNames: List[TermName])( - paramTypesExp: MethodType => List[Type], - resultTypeExp: MethodType => Type) - extends CachedGroundType with BindingType with TermType with MethodOrPoly with NarrowCached { thisMethodType => - import MethodType._ + /** The lambda type square: + * + * LambdaType | LambdaOverTerms | LambdaOverTypes + * ------------+-------------------+------------------ + * Proxy (hk) | HKTermLambda | HKTypeLambda + * Ground (*) | MethodType | PolyType + */ + trait LambdaType extends BindingType with MethodOrPoly { + def paramNames: List[TermName] + def paramTypes: List[Type] + def resType: Type + def newLikeThis(paramNames: List[Name], paramBounds: List[Type], resType: Type)(implicit ctx: Context): LambdaType + def newParamRef(n: Int): ParamRef - def isJava = false - def isImplicit = false + override def resultType(implicit ctx: Context) = resType - val paramTypes = paramTypesExp(this) - private[core] val resType = resultTypeExp(this) - assert(resType.exists) + def isDependent(implicit ctx: Context): Boolean + + final def isTermLambda = paramNames.head.isTermName + final def isTypeLambda = paramNames.head.isTypeName + final def isHigherKinded = isInstanceOf[TypeProxy] + + lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef) + + def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = + if (isDependent) resultType.substParams(this, argTypes) + else resultType + + def derivedLambdaType(paramNames: List[Name] = this.paramNames, + paramTypes: List[Type] = this.paramTypes, + resType: Type = this.resType)(implicit ctx: Context) = + if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (resType eq this.resType)) this + else newLikeThis(paramNames, paramTypes, resType) + + override def equals(that: Any) = that match { + case that: LambdaType => + this.paramNames == that.paramNames && + this.paramTypes == that.paramTypes && + this.resType == that.resType + case _ => + false + } + } + + trait LambdaOverTerms extends LambdaType { thisLambdaType => + import LambdaOverTerms._ override def resultType(implicit ctx: Context): Type = if (dependencyStatus == FalseDeps) { // dealias all false dependencies @@ -2361,7 +2395,7 @@ object Types { if (status == TrueDeps) status else tp match { - case MethodParam(`thisMethodType`, _) => TrueDeps + case ParamRef(`thisLambdaType`, _) => TrueDeps case tp: TypeRef => val status1 = foldOver(status, tp) tp.info match { // follow type alias to avoid dependency @@ -2418,33 +2452,49 @@ object Types { */ def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps + def newParamRef(n: Int): ParamRef = new TermParamRef(this, n) + } + + trait LambdaOverTypes extends LambdaType { thisLambdaType => + } + + object LambdaOverTerms { + private type DependencyStatus = Byte + private final val Unknown: DependencyStatus = 0 // not yet computed + private final val NoDeps: DependencyStatus = 1 // no dependent parameters found + private final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types + private final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist + private final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status + private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations + } + + abstract case class MethodType(paramNames: List[TermName])( + paramTypesExp: MethodType => List[Type], + resultTypeExp: MethodType => Type) + extends CachedGroundType with TermType with LambdaOverTerms with NarrowCached { thisMethodType => + import MethodType._ + + protected def companion: LambdaTypeCompanion[MethodType] + + def isJava = false + def isImplicit = false + + val paramTypes = paramTypesExp(this) + val resType = resultTypeExp(this) + assert(resType.exists) + protected def computeSignature(implicit ctx: Context): Signature = resultSignature.prepend(paramTypes, isJava) def derivedMethodType(paramNames: List[TermName] = this.paramNames, paramTypes: List[Type] = this.paramTypes, resType: Type = this.resType)(implicit ctx: Context) = - if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (resType eq this.resType)) this - else { - val paramTypesFn = (x: MethodType) => paramTypes.map(_.subst(this, x)) - val resTypeFn = (x: MethodType) => resType.subst(this, x) - if (isJava) JavaMethodType(paramNames)(paramTypesFn, resTypeFn) - else if (isImplicit) ImplicitMethodType(paramNames)(paramTypesFn, resTypeFn) - else MethodType(paramNames)(paramTypesFn, resTypeFn) - } - - def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = - if (isDependent) resultType.substParams(this, argTypes) - else resultType + derivedLambdaType(paramNames, paramTypes, resType) - override def equals(that: Any) = that match { - case that: MethodType => - this.paramNames == that.paramNames && - this.paramTypes == that.paramTypes && - this.resType == that.resType - case _ => - false - } + def newLikeThis(paramNames: List[Name], paramTypes: List[Type], resType: Type)(implicit ctx: Context): MethodType = + companion(paramNames.asInstanceOf[List[TermName]])( + x => paramTypes.mapConserve(_.subst(this, x)), + x => resType.subst(this, x)) override def computeHash = doHash(paramNames, resType, paramTypes) @@ -2454,11 +2504,13 @@ object Types { final class CachedMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type) extends MethodType(paramNames)(paramTypesExp, resultTypeExp) { + def companion = MethodType override def equals(that: Any) = super.equals(that) && that.isInstanceOf[CachedMethodType] } final class JavaMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type) extends MethodType(paramNames)(paramTypesExp, resultTypeExp) { + def companion = JavaMethodType override def isJava = true override def equals(that: Any) = super.equals(that) && that.isInstanceOf[JavaMethodType] override def computeHash = addDelta(super.computeHash, 1) @@ -2467,19 +2519,20 @@ object Types { final class ImplicitMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type) extends MethodType(paramNames)(paramTypesExp, resultTypeExp) { + def companion = ImplicitMethodType override def isImplicit = true override def equals(that: Any) = super.equals(that) && that.isInstanceOf[ImplicitMethodType] override def computeHash = addDelta(super.computeHash, 2) override protected def prefixString = "ImplicitMethodType" } - abstract class MethodTypeCompanion { - def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType - def apply(paramNames: List[TermName], paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType = + abstract class LambdaTypeCompanion[LT <: LambdaType] { + def apply(paramNames: List[TermName])(paramTypesExp: LT => List[Type], resultTypeExp: LT => Type)(implicit ctx: Context): LT + def apply(paramNames: List[TermName], paramTypes: List[Type], resultType: Type)(implicit ctx: Context): LT = apply(paramNames)(_ => paramTypes, _ => resultType) - def apply(paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = + def apply(paramTypes: List[Type])(resultTypeExp: LT => Type)(implicit ctx: Context): LT = apply(nme.syntheticParamNames(paramTypes.length))(_ => paramTypes, resultTypeExp) - def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType = + def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): LT = apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType) /** Produce method type from parameter symbols, with special mappings for repeated @@ -2501,8 +2554,8 @@ object Types { case _: ExprType => tp case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot)) } - def integrate(tp: Type, mt: MethodType) = - tp.subst(params, (0 until params.length).toList.map(MethodParam(mt, _))) + def integrate(tp: Type, mt: LT) = + tp.subst(params, params.indices.toList.map(mt.newParamRef)) def paramInfo(param: Symbol): Type = { val paramType = translateRepeated(param.info) if (param.is(Inline)) translateInline(paramType) else paramType @@ -2512,36 +2565,28 @@ object Types { mt => integrate(resultType, mt)) } - def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = { - if (Config.checkMethodTypes) + def checkValid(mt: LT)(implicit ctx: Context): mt.type = { + if (Config.checkMethodTypes && mt.isTermLambda) for ((paramType, idx) <- mt.paramTypes.zipWithIndex) paramType.foreachPart { - case MethodParam(`mt`, j) => assert(j < idx, mt) + case ParamRef(`mt`, j) => assert(j < idx, mt) case _ => } mt } } - object MethodType extends MethodTypeCompanion { + object MethodType extends LambdaTypeCompanion[MethodType] { def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = checkValid(unique(new CachedMethodType(paramNames)(paramTypesExp, resultTypeExp))) - - private type DependencyStatus = Byte - private final val Unknown: DependencyStatus = 0 // not yet computed - private final val NoDeps: DependencyStatus = 1 // no dependent parameters found - private final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types - private final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist - private final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status - private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations } - object JavaMethodType extends MethodTypeCompanion { + object JavaMethodType extends LambdaTypeCompanion[MethodType] { def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = unique(new JavaMethodType(paramNames)(paramTypesExp, resultTypeExp)) } - object ImplicitMethodType extends MethodTypeCompanion { + object ImplicitMethodType extends LambdaTypeCompanion[MethodType] { def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = checkValid(unique(new ImplicitMethodType(paramNames)(paramTypesExp, resultTypeExp))) } @@ -2590,7 +2635,7 @@ object Types { extends CachedProxyType with BindingType with MethodOrPoly { /** The bounds of the type parameters */ - val paramBounds: List[TypeBounds] = paramBoundsExp(this) + val paramTypes: List[Type] = paramBoundsExp(this) /** The result type of a PolyType / body of a type lambda */ val resType: Type = resultTypeExp(this) @@ -2600,11 +2645,6 @@ object Types { protected def computeSignature(implicit ctx: Context) = resultSignature - def isPolymorphicMethodType: Boolean = resType match { - case _: MethodType => true - case _ => false - } - /** PolyParam references to all type parameters of this type */ lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _)) @@ -2619,8 +2659,8 @@ object Types { resultType.substParams(this, argTypes) /** Instantiate parameter bounds by substituting parameters with given arguments */ - final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[TypeBounds] = - paramBounds.mapConserve(_.substParams(this, argTypes).bounds) + final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] = + paramTypes.mapConserve(_.substParams(this, argTypes)) def newLikeThis(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType = PolyType.apply(paramNames)( @@ -2666,7 +2706,7 @@ object Types { /** The type `[tparams := paramRefs] tp`, where `tparams` can be * either a list of type parameter symbols or a list of lambda parameters */ - def lifted(tparams: List[TypeParamInfo], tp: Type)(implicit ctx: Context): Type = + def lifted(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type = tparams match { case LambdaParam(poly, _) :: _ => tp.subst(poly, this) case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs) @@ -2680,9 +2720,9 @@ object Types { case _ => false } - override def toString = s"PolyType($paramNames, $paramBounds, $resType)" + override def toString = s"PolyType($paramNames, $paramTypes, $resType)" - override def computeHash = doHash(paramNames, resType, paramBounds) + override def computeHash = doHash(paramNames, resType, paramTypes) } object PolyType { @@ -2703,12 +2743,12 @@ object Types { // ----- HK types: LambdaParam, HKApply --------------------- /** The parameter of a type lambda */ - case class LambdaParam(tl: PolyType, n: Int) extends TypeParamInfo { - def isTypeParam(implicit ctx: Context) = true + case class LambdaParam(tl: PolyType, n: Int) extends ParamInfo { + def isTypeParam(implicit ctx: Context) = tl.paramNames.head.isTypeName def paramName(implicit ctx: Context): TypeName = tl.paramNames(n) - def paramBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n) - def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = paramBounds - def paramBoundsOrCompleter(implicit ctx: Context): Type = paramBounds + def paramInfo(implicit ctx: Context): Type = tl.paramBounds(n) + def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type = paramInfo + def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance def toArg: Type = PolyParam(tl, n) def paramRef(implicit ctx: Context): Type = PolyParam(tl, n) @@ -2750,7 +2790,7 @@ object Types { NoType } - def typeParams(implicit ctx: Context): List[TypeParamInfo] = { + def typeParams(implicit ctx: Context): List[ParamInfo] = { val tparams = tycon.typeParams if (tparams.isEmpty) PolyType.any(args.length).typeParams else tparams } @@ -2801,32 +2841,34 @@ object Types { def paramName: Name } - abstract case class MethodParam(binder: MethodType, paramNum: Int) extends ParamType with SingletonType { - type BT = MethodType + abstract case class ParamRef(binder: LambdaType, paramNum: Int) extends ParamType { + type BT = LambdaType def paramName = binder.paramNames(paramNum) override def underlying(implicit ctx: Context): Type = binder.paramTypes(paramNum) - def copyBoundType(bt: BT) = new MethodParamImpl(bt, paramNum) // need to customize hashCode and equals to prevent infinite recursion for dep meth types. override def computeHash = addDelta(binder.identityHash, paramNum) override def equals(that: Any) = that match { - case that: MethodParam => + case that: ParamRef => (this.binder eq that.binder) && this.paramNum == that.paramNum case _ => false } - override def toString = s"MethodParam($paramName)" + override def toString = s"ParamRef($paramName)" } - class MethodParamImpl(binder: MethodType, paramNum: Int) extends MethodParam(binder, paramNum) + class TermParamRef(binder: LambdaType, paramNum: Int) + extends ParamRef(binder, paramNum) with SingletonType { + def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum) + } - object MethodParam { - def apply(binder: MethodType, paramNum: Int)(implicit ctx: Context): MethodParam = { + object TermParamRef { + def apply(binder: LambdaType, paramNum: Int)(implicit ctx: Context): TermParamRef = { assertUnerased() - new MethodParamImpl(binder, paramNum) + new TermParamRef(binder, paramNum) } } @@ -3510,7 +3552,7 @@ object Types { if (inst.exists) apply(inst) else tp case tp: HKApply => - def mapArg(arg: Type, tparam: TypeParamInfo): Type = { + def mapArg(arg: Type, tparam: ParamInfo): Type = { val saved = variance variance *= tparam.paramVariance try this(arg) @@ -3725,7 +3767,7 @@ object Types { this(x, prefix) case tp @ HKApply(tycon, args) => - @tailrec def foldArgs(x: T, tparams: List[TypeParamInfo], args: List[Type]): T = + @tailrec def foldArgs(x: T, tparams: List[ParamInfo], args: List[Type]): T = if (args.isEmpty) { assert(tparams.isEmpty) x @@ -3815,7 +3857,7 @@ object Types { apply(x, tp.tref) case tp: ConstantType => apply(x, tp.underlying) - case tp: MethodParam => + case tp: ParamRef => apply(x, tp.underlying) case tp: PolyParam => apply(x, tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 871f39838..d0d0e1863 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -266,7 +266,7 @@ class TreePickler(pickler: TastyPickler) { case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) case _ => assert(false, s"orphan poly parameter: $tpe") } - case tpe: MethodParam => + case tpe: ParamRef => assert(pickleParamType(tpe), s"orphan method parameter: $tpe") case tpe: LazyRef => pickleType(tpe.ref) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 6c6ebc0a3..067fd6076 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -284,7 +284,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle case PARAMtype => readTypeRef() match { case binder: PolyType => PolyParam(binder, readNat()) - case binder: MethodType => MethodParam(binder, readNat()) + case binder: MethodType => binder.newParamRef(readNat()) } case CLASSconst => ConstantType(Constant(readType())) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index ba5592bd6..bc6897c12 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -208,7 +208,7 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def polyParamNameString(name: TypeName): String = name.toString - protected def polyParamNameString(param: PolyParam): String = + protected def polyParamNameString(param: PolyParam): String = polyParamNameString(param.binder.paramNames(param.paramNum)) /** The name of the symbol without a unique id. Under refined printing, @@ -259,8 +259,8 @@ class PlainPrinter(_ctx: Context) extends Printer { "Super(" ~ toTextGlobal(thistpe) ~ ")" case tp @ ConstantType(value) => toText(value) - case MethodParam(mt, idx) => - nameString(mt.paramNames(idx)) + case pref: TermParamRef => + nameString(pref.binder.paramNames(pref.paramNum)) case tp: RecThis => val idx = openRecs.reverse.indexOf(tp.binder) if (idx >= 0) selfRecName(idx + 1) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index b0f5f8ab1..87837fd82 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -617,7 +617,7 @@ object messages { |""" } - case class WrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree])(implicit ctx: Context) + case class WrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree])(implicit ctx: Context) extends Message(WrongNumberOfTypeArgsID) { val kind = "Syntax" @@ -625,7 +625,7 @@ object messages { private val actualCount = actual.length private val msgPrefix = if (actualCount > expectedCount) "Too many" else "Not enough" - //TODO add def simpleParamName to TypeParamInfo + //TODO add def simpleParamName to ParamInfo private val expectedArgString = fntpe .widen.typeParams .map(_.paramName.unexpandedName.show) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 082a80b58..158ba4185 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -497,9 +497,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder new api.Singleton(new api.Path(pathComponents.toArray.reverse ++ Array(Constants.thisPath))) } - def apiTypeParameter(tparam: TypeParamInfo): api.TypeParameter = + def apiTypeParameter(tparam: ParamInfo): api.TypeParameter = apiTypeParameter(tparam.paramName.toString, tparam.paramVariance, - tparam.paramBounds.lo, tparam.paramBounds.hi) + tparam.paramInfo.bounds.lo, tparam.paramInfo.bounds.hi) def apiTypeParameter(name: String, variance: Int, lo: Type, hi: Type): api.TypeParameter = new api.TypeParameter(name, Array(), Array(), apiVariance(variance), diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index fefa63f6f..a02235163 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -256,7 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverse(tp.underlying) case tp: ConstantType => traverse(tp.underlying) - case tp: MethodParam => + case tp: ParamRef => traverse(tp.underlying) case tp: PolyParam => traverse(tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index cdc28b23f..7fb9ba302 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -107,7 +107,7 @@ trait FullParameterization { val firstArgType = if (liftThisType) thisParamType & clazz.thisType else thisParamType MethodType(nme.SELF :: Nil)( mt => firstArgType :: Nil, - mt => mapClassParams(origResult).substThisUnlessStatic(clazz, MethodParam(mt, 0))) + mt => mapClassParams(origResult).substThisUnlessStatic(clazz, mt.newParamRef(0))) } /** Replace class type parameters by the added type parameters of the polytype `pt` */ diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 3c11827fc..8907cc4dd 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -180,7 +180,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { case tpe: PolyType => tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType)) case _ => - MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, MethodParam(mt, 0))) + MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0))) } accTypeOf(sym.info) } @@ -232,7 +232,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { case tpe: PolyType => tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType)) case _ => - MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, MethodParam(mt, 0))) + MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0))) } val accType = accTypeOf(sym.info) val protectedAccessor = clazz.info.decl(accName).suchThat(_.signature == accType.signature).symbol orElse { diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 310121f31..f506abce8 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -395,7 +395,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def addTyped(arg: Arg, formal: Type): Type => Type = { addArg(typedArg(arg, formal), formal) if (methodType.isParamDependent) - _.substParam(MethodParam(methodType, n), typeOfArg(arg)) + _.substParam(methodType.newParamRef(n), typeOfArg(arg)) else identity } @@ -1066,7 +1066,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case _ => // (3) tp2 match { case tp2: MethodType => true // (3a) - case tp2: PolyType if tp2.isPolymorphicMethodType => true // (3a) + case tp2: PolyType if tp2.resultType.isInstanceOf[MethodType] => true // (3a) case tp2: PolyType => // (3b) val nestedCtx = ctx.fresh.setExploreTyperState diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 148ccd6e3..76cbbdc6d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -69,12 +69,12 @@ object Checking { // If `args` is a list of named arguments, return corresponding type parameters, // otherwise return type parameters unchanged val tparams = tycon.tpe.typeParams - def argNamed(tparam: TypeParamInfo) = args.find { + def argNamed(tparam: ParamInfo) = args.find { case NamedArg(name, _) => name == tparam.paramName case _ => false }.getOrElse(TypeTree(tparam.paramRef)) val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args - val bounds = tparams.map(_.paramBoundsAsSeenFrom(tycon.tpe)) + val bounds = tparams.map(_.paramInfoAsSeenFrom(tycon.tpe).bounds) def instantiate(bound: Type, args: List[Type]) = bound.LambdaAbstract(tparams).appliedTo(args) checkBounds(orderedArgs, bounds, instantiate) diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index a1690955f..00e393f7b 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -46,7 +46,7 @@ object ErrorReporting { errorMsg(ex.toMessage, ctx) } - def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree], pos: Position)(implicit ctx: Context) = + def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree], pos: Position)(implicit ctx: Context) = errorType(WrongNumberOfTypeArgs(fntpe, expectedArgs, actual)(ctx), pos) class Errors(implicit ctx: Context) { diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index d61e24261..3f935a8dc 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -485,7 +485,7 @@ object ProtoTypes { case inst => wildApprox(inst, theMap, seen) } approxPoly - case MethodParam(mt, pnum) => + case ParamRef(mt, pnum) => WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum), theMap, seen))) case tp: TypeVar => wildApprox(tp.underlying, theMap, seen) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 6d0fc08f9..93a534f6b 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -106,7 +106,7 @@ trait TypeAssigner { val base = apply(tycon) var args = tp.baseArgInfos(base.typeSymbol) if (base.typeParams.length != args.length) - args = base.typeParams.map(_.paramBounds) + args = base.typeParams.map(_.paramInfo) apply(base.appliedTo(args)) case tp @ RefinedType(parent, name, rinfo) if variance > 0 => val parent1 = apply(tp.parent) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index d4a9744e4..68ff7579f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1074,10 +1074,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit wrongNumberOfTypeArgs(tpt1.tpe, tparams, args, tree.pos) args = args.take(tparams.length) } - def typedArg(arg: untpd.Tree, tparam: TypeParamInfo) = { + def typedArg(arg: untpd.Tree, tparam: ParamInfo) = { val (desugaredArg, argPt) = if (ctx.mode is Mode.Pattern) - (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramBounds) + (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramInfo) else (arg, WildcardType) if (tpt1.symbol.isClass) diff --git a/compiler/src/dotty/tools/dotc/typer/Variances.scala b/compiler/src/dotty/tools/dotc/typer/Variances.scala index 5a1745930..c2a75ee0e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Variances.scala +++ b/compiler/src/dotty/tools/dotc/typer/Variances.scala @@ -84,7 +84,7 @@ object Variances { case ExprType(restpe) => varianceInType(restpe)(tparam) case tp @ HKApply(tycon, args) => - def varianceInArgs(v: Variance, args: List[Type], tparams: List[TypeParamInfo]): Variance = + def varianceInArgs(v: Variance, args: List[Type], tparams: List[ParamInfo]): Variance = args match { case arg :: args1 => varianceInArgs( -- cgit v1.2.3 From 31ab8804d611343eb3cf35e2c1b929d5b65a946e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 16 Mar 2017 17:07:10 +0100 Subject: Harmonize paramTypes and paramBounds MethodTypes have paramTypes whereas PolyTypes have paramBounds. We now harmonize by alling both paramInfos, and parameterizing types that will become common to both. --- .../dotty/tools/backend/jvm/scalaPrimitives.scala | 2 +- compiler/src/dotty/tools/dotc/ast/tpd.scala | 10 +- compiler/src/dotty/tools/dotc/core/Constants.scala | 2 +- .../dotty/tools/dotc/core/ConstraintHandling.scala | 4 +- .../src/dotty/tools/dotc/core/Definitions.scala | 4 +- .../src/dotty/tools/dotc/core/Denotations.scala | 14 +- .../dotty/tools/dotc/core/OrderingConstraint.scala | 2 +- compiler/src/dotty/tools/dotc/core/ParamInfo.scala | 2 +- .../src/dotty/tools/dotc/core/SymDenotations.scala | 4 +- .../dotty/tools/dotc/core/TypeApplications.scala | 2 +- .../src/dotty/tools/dotc/core/TypeComparer.scala | 12 +- .../src/dotty/tools/dotc/core/TypeErasure.scala | 8 +- compiler/src/dotty/tools/dotc/core/Types.scala | 203 +++++++++++---------- .../dotc/core/classfile/ClassfileParser.scala | 4 +- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 6 +- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 6 +- .../dotty/tools/dotc/printing/PlainPrinter.scala | 4 +- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 2 +- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 2 +- .../tools/dotc/transform/CollectEntryPoints.scala | 2 +- .../dotty/tools/dotc/transform/ElimByName.scala | 2 +- .../tools/dotc/transform/ElimErasedValueType.scala | 2 +- .../dotty/tools/dotc/transform/ElimRepeated.scala | 6 +- .../src/dotty/tools/dotc/transform/Erasure.scala | 12 +- .../dotc/transform/FullParameterization.scala | 4 +- .../dotc/transform/FunctionalInterfaces.scala | 6 +- .../src/dotty/tools/dotc/transform/MixinOps.scala | 2 +- .../tools/dotc/transform/PatternMatcher.scala | 2 +- .../tools/dotc/transform/SuperAccessors.scala | 4 +- .../src/dotty/tools/dotc/typer/Applications.scala | 20 +- compiler/src/dotty/tools/dotc/typer/Checking.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Dynamic.scala | 2 +- .../dotty/tools/dotc/typer/ErrorReporting.scala | 2 +- .../src/dotty/tools/dotc/typer/EtaExpansion.scala | 8 +- .../src/dotty/tools/dotc/typer/Implicits.scala | 8 +- .../src/dotty/tools/dotc/typer/Inferencing.scala | 4 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 4 +- compiler/src/dotty/tools/dotc/typer/Namer.scala | 2 +- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 14 +- compiler/src/dotty/tools/dotc/typer/ReTyper.scala | 2 +- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 6 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 16 +- .../src/dotty/tools/dotc/typer/Variances.scala | 4 +- 43 files changed, 216 insertions(+), 213 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala index 89831e56b..7beae90c4 100644 --- a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala +++ b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala @@ -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 } diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index cbb256dd0..8e76d981d 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -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) @@ -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 } @@ -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 @@ -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 { @@ -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) } diff --git a/compiler/src/dotty/tools/dotc/core/Constants.scala b/compiler/src/dotty/tools/dotc/core/Constants.scala index 1892e4bdc..e8b27c0ba 100644 --- a/compiler/src/dotty/tools/dotc/core/Constants.scala +++ b/compiler/src/dotty/tools/dotc/core/Constants.scala @@ -174,7 +174,7 @@ object Constants { 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 diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index a12936c58..34662cbff 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -303,7 +303,7 @@ trait ConstraintHandling { /** The current bounds of type parameter `param` */ final def bounds(param: PolyParam): TypeBounds = { val e = constraint.entry(param) - if (e.exists) e.bounds else param.binder.paramBounds(param.paramNum) + if (e.exists) e.bounds else param.binder.paramInfos(param.paramNum) } /** Add polytype `pt`, possibly with type variables `tvars`, to current constraint @@ -362,7 +362,7 @@ trait ConstraintHandling { def apply(t: Type): Type = t match { case t @ PolyParam(pt: PolyType, n) if comparedPolyTypes contains pt => val effectiveVariance = if (fromBelow) -variance else variance - val bounds = pt.paramBounds(n) + val bounds = pt.paramInfos(n) if (effectiveVariance > 0) bounds.lo else if (effectiveVariance < 0) bounds.hi else NoType diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index c48016b67..0c1d6521d 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -151,8 +151,8 @@ class Definitions { private def enterPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int, resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = { val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount) - val tparamBounds = tparamNames map (_ => TypeBounds.empty) - val ptype = PolyType(tparamNames)(_ => tparamBounds, resultTypeFn) + val tparamInfos = tparamNames map (_ => TypeBounds.empty) + val ptype = PolyType(tparamNames)(_ => tparamInfos, resultTypeFn) enterMethod(cls, name, ptype, flags) } diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index f726cd0d1..1d7b3c94c 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -213,7 +213,7 @@ object Denotations { def requiredMethod(name: PreName, argTypes: List[Type])(implicit ctx: Context): TermSymbol = info.member(name.toTermName).requiredSymbol(x=> - (x is Method) && x.info.paramTypess == List(argTypes) + (x is Method) && x.info.paramInfoss == List(argTypes) ).asTerm def requiredMethodRef(name: PreName, argTypes: List[Type])(implicit ctx: Context): TermRef = requiredMethod(name, argTypes).termRef @@ -310,11 +310,11 @@ object Denotations { } case tp1: MethodType if isTerm => tp2 match { - case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) && + case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && tp1.isImplicit == tp2.isImplicit => tp1.derivedMethodType( mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName), - tp1.paramTypes, + tp1.paramInfos, infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1))) case _ => mergeConflict(tp1, tp2) @@ -324,7 +324,7 @@ object Denotations { case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) => tp1.derivedPolyType( mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), - tp1.paramBounds, + tp1.paramInfos, infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1))) case _: MethodicType => mergeConflict(tp1, tp2) @@ -474,11 +474,11 @@ object Denotations { case tp1: MethodType => tp2 match { case tp2: MethodType - if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) && + if ctx.typeComparer.matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && tp1.isImplicit == tp2.isImplicit => tp1.derivedMethodType( mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName), - tp1.paramTypes, tp1.resultType | tp2.resultType.subst(tp2, tp1)) + tp1.paramInfos, tp1.resultType | tp2.resultType.subst(tp2, tp1)) case _ => mergeConflict(tp1, tp2) } @@ -487,7 +487,7 @@ object Denotations { case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) => tp1.derivedPolyType( mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), - tp1.paramBounds, tp1.resultType | tp2.resultType.subst(tp2, tp1)) + tp1.paramInfos, tp1.resultType | tp2.resultType.subst(tp2, tp1)) case _ => mergeConflict(tp1, tp2) } diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 61dd5a445..3387f20e3 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -284,7 +284,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, assert(!contains(poly)) val nparams = poly.paramNames.length val entries1 = new Array[Type](nparams * 2) - poly.paramBounds.copyToArray(entries1, 0) + poly.paramInfos.copyToArray(entries1, 0) tvars.copyToArray(entries1, nparams) newConstraint(boundsMap.updated(poly, entries1), lowerMap, upperMap).init(poly) } diff --git a/compiler/src/dotty/tools/dotc/core/ParamInfo.scala b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala index efae24916..f824c3e9c 100644 --- a/compiler/src/dotty/tools/dotc/core/ParamInfo.scala +++ b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala @@ -22,7 +22,7 @@ trait ParamInfo { /** The info of the type parameter as seen from a prefix type. * For type parameter symbols, this is the `memberInfo` as seen from `prefix`. - * For type lambda parameters, it's the same as `paramBounds` as + * For type lambda parameters, it's the same as `paramInfos` as * `asSeenFrom` has already been applied to the whole type lambda. */ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 27782698d..c126b5500 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1146,8 +1146,8 @@ object SymDenotations { case tp: NamedType => hasSkolems(tp.prefix) case tp: RefinedType => hasSkolems(tp.parent) || hasSkolems(tp.refinedInfo) case tp: RecType => hasSkolems(tp.parent) - case tp: PolyType => tp.paramBounds.exists(hasSkolems) || hasSkolems(tp.resType) - case tp: MethodType => tp.paramTypes.exists(hasSkolems) || hasSkolems(tp.resType) + case tp: PolyType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) + case tp: MethodType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) case tp: ExprType => hasSkolems(tp.resType) case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems) case tp: AndOrType => hasSkolems(tp.tp1) || hasSkolems(tp.tp2) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 9a1a3359e..931f0dc74 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -369,7 +369,7 @@ class TypeApplications(val self: Type) extends AnyVal { PolyType( (tparams, hkParams).zipped.map((tparam, hkparam) => tparam.paramName.withVariance(hkparam.paramVariance)))( - tl => arg.paramBounds.map(_.subst(arg, tl).bounds), + tl => arg.paramInfos.map(_.subst(arg, tl).bounds), tl => arg.resultType.subst(arg, tl) ) case arg @ TypeAlias(alias) => diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index fb16a6772..9f4db5edd 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -488,7 +488,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def compareMethod = tp1 match { case tp1: MethodType => (tp1.signature consistentParams tp2.signature) && - matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) && + matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && (tp1.isImplicit == tp2.isImplicit) && isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1)) case _ => @@ -1021,7 +1021,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { tp2.widen match { case tp2: MethodType => // implicitness is ignored when matching - matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) && + matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) case tp2 => relaxed && tp1.paramNames.isEmpty && @@ -1067,7 +1067,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * have the same bounds (after renaming one set to the other)? */ def matchingTypeParams(poly1: PolyType, poly2: PolyType): Boolean = - (poly1.paramBounds corresponds poly2.paramBounds)((b1, b2) => + (poly1.paramInfos corresponds poly2.paramInfos)((b1, b2) => isSameType(b1, b2.subst(poly2, poly1))) // Type equality =:= @@ -1284,7 +1284,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2) .zipped.map((pname, tparam1, tparam2) => pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))( - paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => + paramInfosExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => tl.lifted(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds & tl.lifted(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds), resultTypeExp = tl => @@ -1392,8 +1392,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp2: MethodType => def asGoodParams(formals1: List[Type], formals2: List[Type]) = (formals2 corresponds formals1)(isSubTypeWhenFrozen) - asGoodParams(tp1.paramTypes, tp2.paramTypes) && - (!asGoodParams(tp2.paramTypes, tp1.paramTypes) || + asGoodParams(tp1.paramInfos, tp2.paramInfos) && + (!asGoodParams(tp2.paramInfos, tp1.paramInfos) || isAsGood(tp1.resultType, tp2.resultType)) case _ => false diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index fe3396fcb..b716318c1 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -55,7 +55,7 @@ object TypeErasure { case ThisType(tref) => isErasedType(tref) case tp: MethodType => - tp.paramTypes.forall(isErasedType) && isErasedType(tp.resultType) + tp.paramInfos.forall(isErasedType) && isErasedType(tp.resultType) case tp @ ClassInfo(pre, _, parents, decls, _) => isErasedType(pre) && parents.forall(isErasedType) //&& decls.forall(sym => isErasedType(sym.info)) && isErasedType(tp.selfType) case NoType | NoPrefix | WildcardType | _: ErrorType | SuperType(_, _) => @@ -186,7 +186,7 @@ object TypeErasure { case einfo: MethodType => if (sym.isGetter && einfo.resultType.isRef(defn.UnitClass)) MethodType(Nil, defn.BoxedUnitType) - else if (sym.isAnonymousFunction && einfo.paramTypes.length > MaxImplementedFunctionArity) + else if (sym.isAnonymousFunction && einfo.paramInfos.length > MaxImplementedFunctionArity) MethodType(nme.ALLARGS :: Nil, JavaArrayType(defn.ObjectType) :: Nil, einfo.resultType) else einfo @@ -382,10 +382,10 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean case tp: MethodType => def paramErasure(tpToErase: Type) = erasureFn(tp.isJava, semiEraseVCs, isConstructor, wildcardOK)(tpToErase) - val formals = tp.paramTypes.mapConserve(paramErasure) + val formals = tp.paramInfos.mapConserve(paramErasure) eraseResult(tp.resultType) match { case rt: MethodType => - tp.derivedMethodType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramTypes, rt.resultType) + tp.derivedMethodType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramInfos, rt.resultType) case rt => tp.derivedMethodType(tp.paramNames, formals, rt) } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 17879f168..60d77446d 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -217,7 +217,7 @@ object Types { */ def isVarArgsMethod(implicit ctx: Context): Boolean = this match { case tp: PolyType => tp.resultType.isVarArgsMethod - case mt: MethodType => mt.paramTypes.nonEmpty && mt.paramTypes.last.isRepeatedParam + case mt: MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam case _ => false } @@ -443,7 +443,7 @@ object Types { case tp: TermRef => go (tp.underlying match { case mt: MethodType - if mt.paramTypes.isEmpty && (tp.symbol is Stable) => mt.resultType + if mt.paramInfos.isEmpty && (tp.symbol is Stable) => mt.resultType case tp1 => tp1 }) case tp: PolyParam => @@ -543,7 +543,7 @@ object Types { def goApply(tp: HKApply) = tp.tycon match { case tl: PolyType => go(tl.resType).mapInfo(info => - tl.derivedLambdaAbstraction(tl.paramNames, tl.paramBounds, info).appliedTo(tp.args)) + tl.derivedLambdaAbstraction(tl.paramNames, tl.paramInfos, info).appliedTo(tp.args)) case _ => go(tp.superType) } @@ -1088,9 +1088,9 @@ object Types { } /** The parameter types of a PolyType or MethodType, Empty list for others */ - final def paramTypess(implicit ctx: Context): List[List[Type]] = this match { - case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess - case pt: PolyType => pt.resultType.paramTypess + final def paramInfoss(implicit ctx: Context): List[List[Type]] = this match { + case mt: MethodType => mt.paramInfos :: mt.resultType.paramInfoss + case pt: PolyType => pt.resultType.paramInfoss case _ => Nil } @@ -1103,14 +1103,14 @@ object Types { /** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */ - @tailrec final def firstParamTypes(implicit ctx: Context): List[Type] = this match { - case mt: MethodType => mt.paramTypes + final def firstParamTypes(implicit ctx: Context): List[Type] = this match { + case mt: MethodType => mt.paramInfos case pt: PolyType => pt.resultType.firstParamTypes case _ => Nil } /** Is this either not a method at all, or a parameterless method? */ - @tailrec final def isParameterless(implicit ctx: Context): Boolean = this match { + final def isParameterless(implicit ctx: Context): Boolean = this match { case mt: MethodType => false case pt: PolyType => pt.resultType.isParameterless case _ => true @@ -1220,7 +1220,7 @@ object Types { */ def toFunctionType(dropLast: Int = 0)(implicit ctx: Context): Type = this match { case mt: MethodType if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) => - val formals1 = if (dropLast == 0) mt.paramTypes else mt.paramTypes dropRight dropLast + val formals1 = if (dropLast == 0) mt.paramInfos else mt.paramInfos dropRight dropLast defn.FunctionOf( formals1 mapConserve (_.underlyingIfRepeated(mt.isJava)), mt.resultType, mt.isImplicit && !ctx.erasedTypes) } @@ -2324,12 +2324,12 @@ object Types { * Proxy (hk) | HKTermLambda | HKTypeLambda * Ground (*) | MethodType | PolyType */ - trait LambdaType extends BindingType with MethodOrPoly { + trait LambdaType[PInfo <: Type] extends BindingType with MethodOrPoly { def paramNames: List[TermName] - def paramTypes: List[Type] + def paramInfos: List[PInfo] def resType: Type - def newLikeThis(paramNames: List[Name], paramBounds: List[Type], resType: Type)(implicit ctx: Context): LambdaType - def newParamRef(n: Int): ParamRef + def newLikeThis(paramNames: List[Name], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): LambdaType[PInfo] + def newParamRef(n: Int): ParamRef[PInfo] override def resultType(implicit ctx: Context) = resType @@ -2339,29 +2339,29 @@ object Types { final def isTypeLambda = paramNames.head.isTypeName final def isHigherKinded = isInstanceOf[TypeProxy] - lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef) + lazy val paramRefs: List[ParamRef[PInfo]] = paramNames.indices.toList.map(newParamRef) def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = if (isDependent) resultType.substParams(this, argTypes) else resultType def derivedLambdaType(paramNames: List[Name] = this.paramNames, - paramTypes: List[Type] = this.paramTypes, + paramInfos: List[PInfo] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = - if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (resType eq this.resType)) this - else newLikeThis(paramNames, paramTypes, resType) + if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this + else newLikeThis(paramNames, paramInfos, resType) override def equals(that: Any) = that match { - case that: LambdaType => + case that: LambdaType[_] => this.paramNames == that.paramNames && - this.paramTypes == that.paramTypes && + this.paramInfos == that.paramInfos && this.resType == that.resType case _ => false } } - trait LambdaOverTerms extends LambdaType { thisLambdaType => + trait LambdaOverTerms extends LambdaType[Type] { thisLambdaType => import LambdaOverTerms._ override def resultType(implicit ctx: Context): Type = @@ -2435,8 +2435,8 @@ object Types { if (myParamDependencyStatus != Unknown) myParamDependencyStatus else { val result = - if (paramTypes.isEmpty) NoDeps - else (NoDeps /: paramTypes.tail)(depStatus(_, _)) + if (paramInfos.isEmpty) NoDeps + else (NoDeps /: paramInfos.tail)(depStatus(_, _)) if ((result & Provisional) == 0) myParamDependencyStatus = result (result & StatusMask).toByte } @@ -2452,10 +2452,10 @@ object Types { */ def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps - def newParamRef(n: Int): ParamRef = new TermParamRef(this, n) + def newParamRef(n: Int): ParamRef[Type] = new TermParamRef(this, n) } - trait LambdaOverTypes extends LambdaType { thisLambdaType => + trait LambdaOverTypes extends LambdaType[TypeBounds] { thisLambdaType => } object LambdaOverTerms { @@ -2469,47 +2469,47 @@ object Types { } abstract case class MethodType(paramNames: List[TermName])( - paramTypesExp: MethodType => List[Type], + paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) extends CachedGroundType with TermType with LambdaOverTerms with NarrowCached { thisMethodType => import MethodType._ - protected def companion: LambdaTypeCompanion[MethodType] + protected def companion: MethodTypeCompanion def isJava = false def isImplicit = false - val paramTypes = paramTypesExp(this) + val paramInfos = paramInfosExp(this) val resType = resultTypeExp(this) assert(resType.exists) protected def computeSignature(implicit ctx: Context): Signature = - resultSignature.prepend(paramTypes, isJava) + resultSignature.prepend(paramInfos, isJava) def derivedMethodType(paramNames: List[TermName] = this.paramNames, - paramTypes: List[Type] = this.paramTypes, + paramInfos: List[Type] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = - derivedLambdaType(paramNames, paramTypes, resType) + derivedLambdaType(paramNames, paramInfos, resType) - def newLikeThis(paramNames: List[Name], paramTypes: List[Type], resType: Type)(implicit ctx: Context): MethodType = + def newLikeThis(paramNames: List[Name], paramInfos: List[Type], resType: Type)(implicit ctx: Context): MethodType = companion(paramNames.asInstanceOf[List[TermName]])( - x => paramTypes.mapConserve(_.subst(this, x)), + x => paramInfos.mapConserve(_.subst(this, x)), x => resType.subst(this, x)) - override def computeHash = doHash(paramNames, resType, paramTypes) + override def computeHash = doHash(paramNames, resType, paramInfos) protected def prefixString = "MethodType" - override def toString = s"$prefixString($paramNames, $paramTypes, $resType)" + override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" } - final class CachedMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends MethodType(paramNames)(paramTypesExp, resultTypeExp) { + final class CachedMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) + extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { def companion = MethodType override def equals(that: Any) = super.equals(that) && that.isInstanceOf[CachedMethodType] } - final class JavaMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends MethodType(paramNames)(paramTypesExp, resultTypeExp) { + final class JavaMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) + extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { def companion = JavaMethodType override def isJava = true override def equals(that: Any) = super.equals(that) && that.isInstanceOf[JavaMethodType] @@ -2517,8 +2517,8 @@ object Types { override protected def prefixString = "JavaMethodType" } - final class ImplicitMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends MethodType(paramNames)(paramTypesExp, resultTypeExp) { + final class ImplicitMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) + extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { def companion = ImplicitMethodType override def isImplicit = true override def equals(that: Any) = super.equals(that) && that.isInstanceOf[ImplicitMethodType] @@ -2526,15 +2526,17 @@ object Types { override protected def prefixString = "ImplicitMethodType" } - abstract class LambdaTypeCompanion[LT <: LambdaType] { - def apply(paramNames: List[TermName])(paramTypesExp: LT => List[Type], resultTypeExp: LT => Type)(implicit ctx: Context): LT - def apply(paramNames: List[TermName], paramTypes: List[Type], resultType: Type)(implicit ctx: Context): LT = - apply(paramNames)(_ => paramTypes, _ => resultType) - def apply(paramTypes: List[Type])(resultTypeExp: LT => Type)(implicit ctx: Context): LT = - apply(nme.syntheticParamNames(paramTypes.length))(_ => paramTypes, resultTypeExp) - def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): LT = - apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType) + abstract class LambdaTypeCompanion[PInfo <: Type, LT <: LambdaType[PInfo]] { + def apply(paramNames: List[TermName])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT + def apply(paramNames: List[TermName], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = + apply(paramNames)(_ => paramInfos, _ => resultType) + def apply(paramInfos: List[PInfo])(resultTypeExp: LT => Type)(implicit ctx: Context): LT = + apply(nme.syntheticParamNames(paramInfos.length))(_ => paramInfos, resultTypeExp) + def apply(paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = + apply(nme.syntheticParamNames(paramInfos.length), paramInfos, resultType) + } + abstract class MethodTypeCompanion extends LambdaTypeCompanion[Type, MethodType] { /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters. */ @@ -2554,8 +2556,9 @@ object Types { case _: ExprType => tp case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot)) } - def integrate(tp: Type, mt: LT) = + def integrate(tp: Type, mt: MethodType): Type = tp.subst(params, params.indices.toList.map(mt.newParamRef)) + def paramInfo(param: Symbol): Type = { val paramType = translateRepeated(param.info) if (param.is(Inline)) translateInline(paramType) else paramType @@ -2565,10 +2568,10 @@ object Types { mt => integrate(resultType, mt)) } - def checkValid(mt: LT)(implicit ctx: Context): mt.type = { - if (Config.checkMethodTypes && mt.isTermLambda) - for ((paramType, idx) <- mt.paramTypes.zipWithIndex) - paramType.foreachPart { + def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = { + if (Config.checkMethodTypes) + for ((paramInfo, idx) <- mt.paramInfos.zipWithIndex) + paramInfo.foreachPart { case ParamRef(`mt`, j) => assert(j < idx, mt) case _ => } @@ -2576,25 +2579,25 @@ object Types { } } - object MethodType extends LambdaTypeCompanion[MethodType] { - def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = - checkValid(unique(new CachedMethodType(paramNames)(paramTypesExp, resultTypeExp))) + object MethodType extends MethodTypeCompanion { + def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = + checkValid(unique(new CachedMethodType(paramNames)(paramInfosExp, resultTypeExp))) } - object JavaMethodType extends LambdaTypeCompanion[MethodType] { - def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = - unique(new JavaMethodType(paramNames)(paramTypesExp, resultTypeExp)) + object JavaMethodType extends MethodTypeCompanion { + def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = + unique(new JavaMethodType(paramNames)(paramInfosExp, resultTypeExp)) } - object ImplicitMethodType extends LambdaTypeCompanion[MethodType] { - def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = - checkValid(unique(new ImplicitMethodType(paramNames)(paramTypesExp, resultTypeExp))) + object ImplicitMethodType extends MethodTypeCompanion { + def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = + checkValid(unique(new ImplicitMethodType(paramNames)(paramInfosExp, resultTypeExp))) } /** A ternary extractor for MethodType */ object MethodTpe { def unapply(mt: MethodType)(implicit ctx: Context) = - Some((mt.paramNames, mt.paramTypes, mt.resultType)) + Some((mt.paramNames, mt.paramInfos, mt.resultType)) } /** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */ @@ -2625,17 +2628,17 @@ object Types { * and every other name designates a non-variant parameter. * * @param paramNames The names `X_0`, ..., `X_n` - * @param paramBoundsExp A function that, given the polytype itself, returns the + * @param paramInfosExp A function that, given the polytype itself, returns the * parameter bounds `B_1`, ..., `B_n` * @param resultTypeExp A function that, given the polytype itself, returns the * result type `T`. */ class PolyType(val paramNames: List[TypeName])( - paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) + paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) extends CachedProxyType with BindingType with MethodOrPoly { /** The bounds of the type parameters */ - val paramTypes: List[Type] = paramBoundsExp(this) + val paramInfos: List[TypeBounds] = paramInfosExp(this) /** The result type of a PolyType / body of a type lambda */ val resType: Type = resultTypeExp(this) @@ -2660,29 +2663,29 @@ object Types { /** Instantiate parameter bounds by substituting parameters with given arguments */ final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] = - paramTypes.mapConserve(_.substParams(this, argTypes)) + paramInfos.mapConserve(_.substParams(this, argTypes)) - def newLikeThis(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType = + def newLikeThis(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType = PolyType.apply(paramNames)( - x => paramBounds mapConserve (_.subst(this, x).bounds), + x => paramInfos.mapConserve(_.subst(this, x).bounds), x => resType.subst(this, x)) def derivedPolyType(paramNames: List[TypeName] = this.paramNames, - paramBounds: List[TypeBounds] = this.paramBounds, + paramInfos: List[TypeBounds] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = - if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (resType eq this.resType)) this - else newLikeThis(paramNames, paramBounds, resType) + if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this + else newLikeThis(paramNames, paramInfos, resType) - def derivedLambdaAbstraction(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): Type = + def derivedLambdaAbstraction(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): Type = resType match { case resType @ TypeAlias(alias) => - resType.derivedTypeAlias(newLikeThis(paramNames, paramBounds, alias)) + resType.derivedTypeAlias(newLikeThis(paramNames, paramInfos, alias)) case resType @ TypeBounds(lo, hi) => resType.derivedTypeBounds( - if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramBounds, lo), - newLikeThis(paramNames, paramBounds, hi)) + if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramInfos, lo), + newLikeThis(paramNames, paramInfos, hi)) case _ => - derivedPolyType(paramNames, paramBounds, resType) + derivedPolyType(paramNames, paramInfos, resType) } /** Merge nested polytypes into one polytype. nested polytypes are normally not supported @@ -2697,8 +2700,8 @@ object Types { } } PolyType(paramNames ++ that.paramNames)( - x => this.paramBounds.mapConserve(_.subst(this, x).bounds) ++ - that.paramBounds.mapConserve(shift(_).subst(that, x).bounds), + x => this.paramInfos.mapConserve(_.subst(this, x).bounds) ++ + that.paramInfos.mapConserve(shift(_).subst(that, x).bounds), x => shift(that.resultType).subst(that, x).subst(this, x)) case _ => this } @@ -2715,21 +2718,21 @@ object Types { override def equals(other: Any) = other match { case other: PolyType => other.paramNames == this.paramNames && - other.paramBounds == this.paramBounds && + other.paramInfos == this.paramInfos && other.resType == this.resType case _ => false } - override def toString = s"PolyType($paramNames, $paramTypes, $resType)" + override def toString = s"PolyType($paramNames, $paramInfos, $resType)" - override def computeHash = doHash(paramNames, resType, paramTypes) + override def computeHash = doHash(paramNames, resType, paramInfos) } object PolyType { def apply(paramNames: List[TypeName])( - paramBoundsExp: PolyType => List[TypeBounds], + paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = { - unique(new PolyType(paramNames)(paramBoundsExp, resultTypeExp)) + unique(new PolyType(paramNames)(paramInfosExp, resultTypeExp)) } def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] = @@ -2746,7 +2749,7 @@ object Types { case class LambdaParam(tl: PolyType, n: Int) extends ParamInfo { def isTypeParam(implicit ctx: Context) = tl.paramNames.head.isTypeName def paramName(implicit ctx: Context): TypeName = tl.paramNames(n) - def paramInfo(implicit ctx: Context): Type = tl.paramBounds(n) + def paramInfo(implicit ctx: Context): Type = tl.paramInfos(n) def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type = paramInfo def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance @@ -2841,17 +2844,17 @@ object Types { def paramName: Name } - abstract case class ParamRef(binder: LambdaType, paramNum: Int) extends ParamType { - type BT = LambdaType + abstract case class ParamRef[PInfo <: Type](binder: LambdaType[PInfo], paramNum: Int) extends ParamType { + type BT = LambdaType[PInfo] def paramName = binder.paramNames(paramNum) - override def underlying(implicit ctx: Context): Type = binder.paramTypes(paramNum) + override def underlying(implicit ctx: Context): Type = binder.paramInfos(paramNum) // need to customize hashCode and equals to prevent infinite recursion for dep meth types. override def computeHash = addDelta(binder.identityHash, paramNum) override def equals(that: Any) = that match { - case that: ParamRef => + case that: ParamRef[_] => (this.binder eq that.binder) && this.paramNum == that.paramNum case _ => false @@ -2860,13 +2863,13 @@ object Types { override def toString = s"ParamRef($paramName)" } - class TermParamRef(binder: LambdaType, paramNum: Int) - extends ParamRef(binder, paramNum) with SingletonType { + class TermParamRef(binder: LambdaType[Type], paramNum: Int) + extends ParamRef[Type](binder, paramNum) with SingletonType { def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum) } object TermParamRef { - def apply(binder: LambdaType, paramNum: Int)(implicit ctx: Context): TermParamRef = { + def apply(binder: LambdaType[Type], paramNum: Int)(implicit ctx: Context): TermParamRef = { assertUnerased() new TermParamRef(binder, paramNum) } @@ -2893,7 +2896,7 @@ object Types { def paramName = binder.paramNames(paramNum) override def underlying(implicit ctx: Context): Type = { - val bounds = binder.paramBounds + val bounds = binder.paramInfos if (bounds == null) NoType // this can happen if the referenced generic type is not initialized yet else bounds(paramNum) } @@ -3396,7 +3399,7 @@ object Types { case tp: ClassInfo => def zeroParams(tp: Type): Boolean = tp match { case pt: PolyType => zeroParams(pt.resultType) - case mt: MethodType => mt.paramTypes.isEmpty && !mt.resultType.isInstanceOf[MethodType] + case mt: MethodType => mt.paramInfos.isEmpty && !mt.resultType.isInstanceOf[MethodType] case et: ExprType => true case _ => false } @@ -3517,7 +3520,7 @@ object Types { case tp: MethodType => def mapOverMethod = { variance = -variance - val ptypes1 = tp.paramTypes mapConserve this + val ptypes1 = tp.paramInfos mapConserve this variance = -variance derivedMethodType(tp, ptypes1, this(tp.resultType)) } @@ -3529,7 +3532,7 @@ object Types { case tp: PolyType => def mapOverPoly = { variance = -variance - val bounds1 = tp.paramBounds.mapConserve(this).asInstanceOf[List[TypeBounds]] + val bounds1 = tp.paramInfos.mapConserve(this).asInstanceOf[List[TypeBounds]] variance = -variance derivedPolyType(tp, bounds1, this(tp.resultType)) } @@ -3744,7 +3747,7 @@ object Types { case tp: MethodType => variance = -variance - val y = foldOver(x, tp.paramTypes) + val y = foldOver(x, tp.paramInfos) variance = -variance this(y, tp.resultType) @@ -3753,7 +3756,7 @@ object Types { case tp: PolyType => variance = -variance - val y = foldOver(x, tp.paramBounds) + val y = foldOver(x, tp.paramInfos) variance = -variance this(y, tp.resultType) @@ -3857,7 +3860,7 @@ object Types { apply(x, tp.tref) case tp: ConstantType => apply(x, tp.underlying) - case tp: ParamRef => + case tp: ParamRef[_] => apply(x, tp.underlying) case tp: PolyParam => apply(x, tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index e0b233ce8..2bb929bf3 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -209,7 +209,7 @@ class ClassfileParser( def normalizeConstructorInfo() = { val mt @ MethodType(paramNames) = denot.info val rt = classRoot.typeRef appliedTo (classRoot.typeParams map (_.typeRef)) - denot.info = mt.derivedMethodType(paramNames, mt.paramTypes, rt) + denot.info = mt.derivedMethodType(paramNames, mt.paramInfos, rt) addConstructorTypeParams(denot) } @@ -975,7 +975,7 @@ class ClassfileParser( if (name == nme.CONSTRUCTOR) tpe match { case tp: MethodType => - tp.derivedMethodType(tp.paramNames, tp.paramTypes, ownerTpe) + tp.derivedMethodType(tp.paramNames, tp.paramInfos, ownerTpe) } p = (name, tpe) values(index) = p diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index d0d0e1863..8801eb19b 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -255,10 +255,10 @@ class TreePickler(pickler: TastyPickler) { pickleType(tpe.underlying) case tpe: PolyType => writeByte(POLYtype) - pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramBounds) + pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) case tpe: MethodType if richTypes => writeByte(METHODtype) - pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramTypes) + pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) case tpe: PolyParam => if (!pickleParamType(tpe)) // TODO figure out why this case arises in e.g. pickling AbstractFileReader. @@ -266,7 +266,7 @@ class TreePickler(pickler: TastyPickler) { case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) case _ => assert(false, s"orphan poly parameter: $tpe") } - case tpe: ParamRef => + case tpe: ParamRef[_] => assert(pickleParamType(tpe), s"orphan method parameter: $tpe") case tpe: LazyRef => pickleType(tpe.ref) diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 688a2d007..fad516da7 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -56,7 +56,7 @@ object Scala2Unpickler { */ def arrayToRepeated(tp: Type)(implicit ctx: Context): Type = tp match { case tp: MethodType => - val lastArg = tp.paramTypes.last + val lastArg = tp.paramInfos.last assert(lastArg isRef defn.ArrayClass) val elemtp0 :: Nil = lastArg.baseArgInfos(defn.ArrayClass) val elemtp = elemtp0 match { @@ -67,10 +67,10 @@ object Scala2Unpickler { } tp.derivedMethodType( tp.paramNames, - tp.paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp), + tp.paramInfos.init :+ defn.RepeatedParamType.appliedTo(elemtp), tp.resultType) case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramBounds, arrayToRepeated(tp.resultType)) + tp.derivedPolyType(tp.paramNames, tp.paramInfos, arrayToRepeated(tp.resultType)) } def ensureConstructor(cls: ClassSymbol, scope: Scope)(implicit ctx: Context) = diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index bc6897c12..d6b7adffe 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -170,7 +170,7 @@ class PlainPrinter(_ctx: Context) extends Printer { def paramText(name: TermName, tp: Type) = toText(name) ~ ": " ~ toText(tp) changePrec(GlobalPrec) { (if (tp.isImplicit) "(implicit " else "(") ~ - Text((tp.paramNames, tp.paramTypes).zipped map paramText, ", ") ~ + Text((tp.paramNames, tp.paramInfos).zipped map paramText, ", ") ~ ")" ~ toText(tp.resultType) } case tp: ExprType => @@ -178,7 +178,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case tp: PolyType => def paramText(name: Name, bounds: TypeBounds): Text = name.toString ~ toText(bounds) changePrec(GlobalPrec) { - "[" ~ Text((tp.paramNames, tp.paramBounds).zipped.map(paramText), ", ") ~ + "[" ~ Text((tp.paramNames, tp.paramInfos).zipped.map(paramText), ", ") ~ "]" ~ (" => " provided !tp.resultType.isInstanceOf[MethodType]) ~ toTextGlobal(tp.resultType) } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 158ba4185..89e935bd5 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -312,7 +312,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val tparams = sym.info match { case pt: PolyType => - (pt.paramNames, pt.paramBounds).zipped.map((pname, pbounds) => + (pt.paramNames, pt.paramInfos).zipped.map((pname, pbounds) => apiTypeParameter(pname.toString, 0, pbounds.lo, pbounds.hi)) case _ => Nil diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index a02235163..2d5b1ff16 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -256,7 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverse(tp.underlying) case tp: ConstantType => traverse(tp.underlying) - case tp: ParamRef => + case tp: ParamRef[_] => traverse(tp.underlying) case tp: PolyParam => traverse(tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala index 9f1e42e31..e82be4378 100644 --- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala @@ -88,7 +88,7 @@ class CollectEntryPoints extends MiniPhaseTransform { case t: PolyType => fail("main methods cannot be generic.") case t: MethodType => - if (t.resultType :: t.paramTypes exists (_.typeSymbol.isAbstractType)) + if (t.resultType :: t.paramInfos exists (_.typeSymbol.isAbstractType)) fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos) else javaPlatform.isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos) diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala index 59da78590..839552799 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala @@ -93,7 +93,7 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform } val mt @ MethodType(_) = tree.fun.tpe.widen - val args1 = tree.args.zipWithConserve(mt.paramTypes)(transformArg) + val args1 = tree.args.zipWithConserve(mt.paramInfos)(transformArg) cpy.Apply(tree)(tree.fun, args1) } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala index 24c8cdc8d..25c01c1f7 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala @@ -44,7 +44,7 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer { case ErasedValueType(_, underlying) => elimEVT(underlying) case tp: MethodType => - val paramTypes = tp.paramTypes.mapConserve(elimEVT) + val paramTypes = tp.paramInfos.mapConserve(elimEVT) val retType = elimEVT(tp.resultType) tp.derivedMethodType(tp.paramNames, paramTypes, retType) case _ => diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index ae3259509..bc2674a77 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -57,7 +57,7 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati } else paramTypes tp.derivedMethodType(paramNames, paramTypes1, resultType1) case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramBounds, elimRepeated(tp.resultType)) + tp.derivedPolyType(tp.paramNames, tp.paramInfos, elimRepeated(tp.resultType)) case tp => tp } @@ -139,9 +139,9 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati /** Convert type from Scala to Java varargs method */ private def toJavaVarArgs(tp: Type)(implicit ctx: Context): Type = tp match { case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramBounds, toJavaVarArgs(tp.resultType)) + tp.derivedPolyType(tp.paramNames, tp.paramInfos, toJavaVarArgs(tp.resultType)) case tp: MethodType => - val inits :+ last = tp.paramTypes + val inits :+ last = tp.paramInfos val last1 = last.underlyingIfRepeated(isJava = true) tp.derivedMethodType(tp.paramNames, inits :+ last1, tp.resultType) } diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index f9c7a8e1e..d64120085 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -461,12 +461,12 @@ object Erasure extends TypeTestsCasts{ case mt: MethodType => val outers = outer.args(fun.asInstanceOf[tpd.Tree]) // can't use fun1 here because its type is already erased var args0 = outers ::: args ++ protoArgs(pt) - if (args0.length > MaxImplementedFunctionArity && mt.paramTypes.length == 1) { + if (args0.length > MaxImplementedFunctionArity && mt.paramInfos.length == 1) { val bunchedArgs = untpd.JavaSeqLiteral(args0, TypeTree(defn.ObjectType)) .withType(defn.ArrayOf(defn.ObjectType)) args0 = bunchedArgs :: Nil } - val args1 = args0.zipWithConserve(mt.paramTypes)(typedExpr) + val args1 = args0.zipWithConserve(mt.paramInfos)(typedExpr) untpd.cpy.Apply(tree)(fun1, args1) withType mt.resultType case _ => throw new MatchError(i"tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}") @@ -547,8 +547,8 @@ object Erasure extends TypeTestsCasts{ case SAMType(sam) => val implType = meth.tpe.widen - val List(implParamTypes) = implType.paramTypess - val List(samParamTypes) = sam.info.paramTypess + val List(implParamTypes) = implType.paramInfoss + val List(samParamTypes) = sam.info.paramInfoss val implResultType = implType.resultType val samResultType = sam.info.resultType @@ -698,8 +698,8 @@ object Erasure extends TypeTestsCasts{ val rhs = paramss.foldLeft(sel)((fun, vparams) => fun.tpe.widen match { case mt: MethodType => - Apply(fun, (vparams, mt.paramTypes).zipped.map(adapt(_, _, untpd.EmptyTree))) - case a => + Apply(fun, (vparams, mt.paramInfos).zipped.map(adapt(_, _, untpd.EmptyTree))) + case a => error(s"can not resolve apply type $a") }) adapt(rhs, resultType) diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index 7fb9ba302..dd318861a 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -124,7 +124,7 @@ trait FullParameterization { case info: PolyType => PolyType(info.paramNames ++ ctnames)( pt => - (info.paramBounds.map(mapClassParams(_, pt).bounds) ++ + (info.paramInfos.map(mapClassParams(_, pt).bounds) ++ mappedClassBounds(pt)).mapConserve(_.subst(info, pt).bounds), pt => resultType(mapClassParams(_, pt)).subst(info, pt)) case _ => @@ -233,7 +233,7 @@ trait FullParameterization { fun.appliedToArgss(originalDef.vparamss.nestedMap(vparam => ref(vparam.symbol))) else { // this type could have changed on forwarding. Need to insert a cast. - val args = (originalDef.vparamss, fun.tpe.paramTypess).zipped.map((vparams, paramTypes) => + val args = (originalDef.vparamss, fun.tpe.paramInfoss).zipped.map((vparams, paramTypes) => (vparams, paramTypes).zipped.map((vparam, paramType) => { assert(vparam.tpe <:< paramType.widen) // type should still conform to widened type ref(vparam.symbol).ensureConforms(paramType) diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala index 5fd89314a..bde902152 100644 --- a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala +++ b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala @@ -31,8 +31,8 @@ class FunctionalInterfaces extends MiniPhaseTransform { val maxArgsCount = 2 def shouldSpecialize(m: MethodType)(implicit ctx: Context) = - (m.paramTypes.size <= maxArgsCount) && - m.paramTypes.forall(x => allowedArgumentTypes.contains(x.typeSymbol)) && + (m.paramInfos.size <= maxArgsCount) && + m.paramInfos.forall(x => allowedArgumentTypes.contains(x.typeSymbol)) && allowedReturnTypes.contains(m.resultType.typeSymbol) val functionName = "JFunction".toTermName @@ -67,7 +67,7 @@ class FunctionalInterfaces extends MiniPhaseTransform { val names = ctx.atPhase(ctx.erasurePhase) { implicit ctx => functionSymbol.typeParams.map(_.name) } - val interfaceName = (functionName ++ m.paramTypes.length.toString).specializedFor(m.paramTypes ::: m.resultType :: Nil, names, Nil, Nil) + val interfaceName = (functionName ++ m.paramInfos.length.toString).specializedFor(m.paramInfos ::: m.resultType :: Nil, names, Nil, Nil) // symbols loaded from classpath aren't defined in periods earlier than when they where loaded val interface = ctx.withPhase(ctx.typerPhase).getClassIfDefined(functionPackage ++ interfaceName) diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala index 9f7ceeaed..d91522c25 100644 --- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala @@ -72,7 +72,7 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: def hasPrimitiveMissMatch(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match { case (tp1: MethodicType, tp2: MethodicType) => hasPrimitiveMissMatch(tp1.resultType, tp2.resultType) || - tp1.paramTypess.flatten.zip(tp1.paramTypess.flatten).exists(args => hasPrimitiveMissMatch(args._1, args._2)) + tp1.paramInfoss.flatten.zip(tp1.paramInfoss.flatten).exists(args => hasPrimitiveMissMatch(args._1, args._2)) case _ => def isPrimitiveOrValueClass(sym: Symbol): Boolean = sym.isPrimitiveValueClass || sym.isValueClass isPrimitiveOrValueClass(tp1.typeSymbol) ^ isPrimitiveOrValueClass(tp2.typeSymbol) diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 197d18374..dbc7666f7 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -1766,7 +1766,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { def applyMethodTypes(method: Type): Extractor = { val whole = method.finalResultType - method.paramTypess.head match { + method.paramInfoss.head match { case init :+ last if last.isRepeatedParam => newExtractor(whole, init, repeatedFromVarargs(last)) case tps => newExtractor(whole, tps, NoRepeated) } diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 8907cc4dd..102b492a8 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -178,7 +178,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { val accType = { def accTypeOf(tpe: Type): Type = tpe match { case tpe: PolyType => - tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType)) + tpe.derivedPolyType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType)) case _ => MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0))) } @@ -230,7 +230,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { else clazz.classInfo.selfType def accTypeOf(tpe: Type): Type = tpe match { case tpe: PolyType => - tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType)) + tpe.derivedPolyType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType)) case _ => MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0))) } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index f506abce8..d1a73fd65 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -232,7 +232,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => else fail(err.typeMismatchMsg(methType.resultType, resultType)) // match all arguments with corresponding formal parameters - matchArgs(orderedArgs, methType.paramTypes, 0) + matchArgs(orderedArgs, methType.paramInfos, 0) case _ => if (methType.isError) ok = false else fail(s"$methString does not take parameters") @@ -763,7 +763,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val typedFn = typedExpr(tree.fun, PolyProto(typedArgs.tpes, pt)) typedFn.tpe.widen match { case pt: PolyType => - if (typedArgs.length <= pt.paramBounds.length && !isNamed) + if (typedArgs.length <= pt.paramInfos.length && !isNamed) if (typedFn.symbol == defn.Predef_classOf && typedArgs.nonEmpty) { val arg = typedArgs.head checkClassType(arg.tpe, arg.pos, traitReq = false, stablePrefixReq = false) @@ -883,8 +883,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic => } unapplyFn.tpe.widen match { - case mt: MethodType if mt.paramTypes.length == 1 => - val unapplyArgType = mt.paramTypes.head + case mt: MethodType if mt.paramInfos.length == 1 => + val unapplyArgType = mt.paramInfos.head unapp.println(i"unapp arg tpe = $unapplyArgType, pt = $selType") val ownType = if (selType <:< unapplyArgType) { @@ -1056,10 +1056,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case _ => if (tp.isRepeatedParam) tp.argTypesHi.head else tp } val formals1 = - if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramTypes map repeatedToSingle - else tp1.paramTypes + if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramInfos map repeatedToSingle + else tp1.paramInfos isApplicable(alt2, formals1, WildcardType) || - tp1.paramTypes.isEmpty && tp2.isInstanceOf[MethodOrPoly] + tp1.paramInfos.isEmpty && tp2.isInstanceOf[MethodOrPoly] case tp1: PolyType => // (2) val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags, tp1.instantiateBounds) isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2) @@ -1125,7 +1125,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case mt: ImplicitMethodType => resultTypeApprox(mt) case pt: PolyType => - pt.derivedPolyType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType)) + pt.derivedPolyType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType)) case _ => tp } @@ -1287,7 +1287,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def sizeFits(alt: TermRef, tp: Type): Boolean = tp match { case tp: PolyType => sizeFits(alt, tp.resultType) case tp: MethodType => - val ptypes = tp.paramTypes + val ptypes = tp.paramInfos val numParams = ptypes.length def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam def hasDefault = alt.symbol.hasDefaultParams @@ -1413,7 +1413,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case _ => } def paramTypes(alt: Type): List[Type] = alt match { - case mt: MethodType => mt.paramTypes + case mt: MethodType => mt.paramInfos case mt: PolyType => paramTypes(mt.resultType) case _ => Nil } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 76cbbdc6d..e959e6984 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -55,7 +55,7 @@ object Checking { * are handled by method checkBounds in FirstTransform */ def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit = - checkBounds(args, poly.paramBounds, _.substParams(poly, _)) + checkBounds(args, poly.paramInfos, _.substParams(poly, _)) /** Check applied type trees for well-formedness. This means * - all arguments are within their corresponding bounds diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 000cfd026..25fca546e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -150,7 +150,7 @@ trait Dynamic { self: Typer with Applications => |Structural types only support methods taking up to ${Definitions.MaxStructuralMethodArity} arguments""") else { def issueError(msgFn: String => String): Unit = ctx.error(msgFn(""), tree.pos) - val ctags = tpe.paramTypes.map(pt => + val ctags = tpe.paramInfos.map(pt => inferImplicitArg(defn.ClassTagType.appliedTo(pt :: Nil), issueError, tree.pos.endPos)) structuralCall(nme.selectDynamicMethod, ctags).asInstance(tpe.toFunctionType()) } diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 00e393f7b..ff998e233 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -107,7 +107,7 @@ object ErrorReporting { case tp: PolyType => tp.derivedPolyType(resType = dropJavaMethod(tp.resultType)) case tp: JavaMethodType => - MethodType(tp.paramNames, tp.paramTypes, dropJavaMethod(tp.resultType)) + MethodType(tp.paramNames, tp.paramInfos, dropJavaMethod(tp.resultType)) case tp => tp } val found1 = dropJavaMethod(found) diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 57c1808c9..5aee0fd54 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -60,7 +60,7 @@ object EtaExpansion { def liftArgs(defs: mutable.ListBuffer[Tree], methRef: Type, args: List[Tree])(implicit ctx: Context) = methRef.widen match { case mt: MethodType => - (args, mt.paramNames, mt.paramTypes).zipped map { (arg, name, tp) => + (args, mt.paramNames, mt.paramInfos).zipped map { (arg, name, tp) => if (tp.isInstanceOf[ExprType]) arg else liftArg(defs, arg, if (name contains '$') "" else name.toString + "$") } @@ -135,12 +135,12 @@ object EtaExpansion { val defs = new mutable.ListBuffer[tpd.Tree] val lifted: Tree = TypedSplice(liftApp(defs, tree)) val paramTypes: List[Tree] = - if (mt.paramTypes.length == xarity) mt.paramTypes map (_ => TypeTree()) - else mt.paramTypes map TypeTree + if (mt.paramInfos.length == xarity) mt.paramInfos map (_ => TypeTree()) + else mt.paramInfos map TypeTree val params = (mt.paramNames, paramTypes).zipped.map((name, tpe) => ValDef(name, tpe, EmptyTree).withFlags(Synthetic | Param).withPos(tree.pos)) var ids: List[Tree] = mt.paramNames map (name => Ident(name).withPos(tree.pos)) - if (mt.paramTypes.nonEmpty && mt.paramTypes.last.isRepeatedParam) + if (mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam) ids = ids.init :+ repeated(ids.last) var body: Tree = Apply(lifted, ids) mt.resultType match { diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 681045cc4..af2145376 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -66,16 +66,16 @@ object Implicits { def discardForView(tpw: Type, argType: Type): Boolean = tpw match { case mt: MethodType => mt.isImplicit || - mt.paramTypes.length != 1 || - !(argType relaxed_<:< mt.paramTypes.head)(ctx.fresh.setExploreTyperState) + mt.paramInfos.length != 1 || + !(argType relaxed_<:< mt.paramInfos.head)(ctx.fresh.setExploreTyperState) case poly: PolyType => // We do not need to call ProtoTypes#constrained on `poly` because // `refMatches` is always called with mode TypevarsMissContext enabled. poly.resultType match { case mt: MethodType => mt.isImplicit || - mt.paramTypes.length != 1 || - !(argType relaxed_<:< wildApprox(mt.paramTypes.head, null, Set.empty)(ctx.fresh.setExploreTyperState)) + mt.paramInfos.length != 1 || + !(argType relaxed_<:< wildApprox(mt.paramInfos.head, null, Set.empty)(ctx.fresh.setExploreTyperState)) case rtp => discardForView(wildApprox(rtp, null, Set.empty), argType) } diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index 86649d78e..20efd4083 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -157,7 +157,7 @@ object Inferencing { case Apply(fn, _) => fn.tpe.widen match { case mtp: MethodType => - val (occ, nocc) = toTest.partition(tvar => mtp.paramTypes.exists(tvar.occursIn)) + val (occ, nocc) = toTest.partition(tvar => mtp.paramInfos.exists(tvar.occursIn)) occurring(fn, nocc, occ ::: acc) case _ => occurring(fn, toTest, acc) @@ -178,7 +178,7 @@ object Inferencing { */ private def instDirection(param: PolyParam)(implicit ctx: Context): Int = { val constrained = ctx.typerState.constraint.fullBounds(param) - val original = param.binder.paramBounds(param.paramNum) + val original = param.binder.paramInfos(param.paramNum) val cmp = ctx.typeComparer val approxBelow = if (!cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0 diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 6e90367c8..8520dcdfc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -108,7 +108,7 @@ object Inliner { // Add qualifier type as leading method argument to argument `tp` def addQualType(tp: Type): Type = tp match { - case tp: PolyType => tp.derivedPolyType(tp.paramNames, tp.paramBounds, addQualType(tp.resultType)) + case tp: PolyType => tp.derivedPolyType(tp.paramNames, tp.paramInfos, addQualType(tp.resultType)) case tp: ExprType => addQualType(tp.resultType) case tp => MethodType(qualType :: Nil, tp) } @@ -327,7 +327,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { } computeParamBindings(tp.resultType, Nil, argss) case tp: MethodType => - (tp.paramNames, tp.paramTypes, argss.head).zipped.foreach { (name, paramtp, arg) => + (tp.paramNames, tp.paramInfos, argss.head).zipped.foreach { (name, paramtp, arg) => def isByName = paramtp.dealias.isInstanceOf[ExprType] paramBinding(name) = arg.tpe.stripAnnots.stripTypeVar match { case argtpe: SingletonType if isIdempotentExpr(arg) => argtpe diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index ed580c631..3c00d6598 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1032,7 +1032,7 @@ class Namer { typer: Typer => } val defaultAlts = meth.altsWith(_.hasDefaultParams) if (defaultAlts.length == 1) - paramProto(defaultAlts.head.info.widen.paramTypess, idx) + paramProto(defaultAlts.head.info.widen.paramInfoss, idx) else WildcardType } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 3f935a8dc..7406d1786 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -389,7 +389,7 @@ object ProtoTypes { } val added = - if (state.constraint contains pt) pt.newLikeThis(pt.paramNames, pt.paramBounds, pt.resultType) + if (state.constraint contains pt) pt.newLikeThis(pt.paramNames, pt.paramInfos, pt.resultType) else pt val tvars = if (owningTree.isEmpty) Nil else newTypeVars(added) ctx.typeComparer.addToConstraint(added, tvars.tpes.asInstanceOf[List[TypeVar]]) @@ -415,7 +415,7 @@ object ProtoTypes { if (mt.isDependent) { def replacement(tp: Type) = if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepPolyParam(tp) - mt.resultType.substParams(mt, mt.paramTypes.map(replacement)) + mt.resultType.substParams(mt, mt.paramInfos.map(replacement)) } else mt.resultType @@ -444,10 +444,10 @@ object ProtoTypes { val rt = normalize(mt.resultType, pt) pt match { case pt: IgnoredProto => mt - case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramTypes, rt) + case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramInfos, rt) case _ => - val ft = defn.FunctionOf(mt.paramTypes, rt) - if (mt.paramTypes.nonEmpty || ft <:< pt) ft else rt + val ft = defn.FunctionOf(mt.paramInfos, rt) + if (mt.paramInfos.nonEmpty || ft <:< pt) ft else rt } } case et: ExprType => et.resultType @@ -475,7 +475,7 @@ object ProtoTypes { WildcardType(wildApprox(bounds, theMap, seen).bounds) else if (seen.contains(tp)) WildcardType else WildcardType(wildApprox(bounds, theMap, seen + tp).bounds) - def unconstrainedApprox = wildApproxBounds(poly.paramBounds(pnum)) + def unconstrainedApprox = wildApproxBounds(poly.paramInfos(pnum)) def approxPoly = if (ctx.mode.is(Mode.TypevarsMissContext)) unconstrainedApprox else @@ -486,7 +486,7 @@ object ProtoTypes { } approxPoly case ParamRef(mt, pnum) => - WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum), theMap, seen))) + WildcardType(TypeBounds.upper(wildApprox(mt.paramInfos(pnum), theMap, seen))) case tp: TypeVar => wildApprox(tp.underlying, theMap, seen) case tp @ HKApply(tycon, args) => diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index 6080c6644..73e676b57 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -86,7 +86,7 @@ class ReTyper extends Typer { override def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree = fun.tpe match { case mt: MethodType => - val args: List[Tree] = tree.args.zipWithConserve(mt.paramTypes)(typedExpr(_, _)).asInstanceOf[List[Tree]] + val args: List[Tree] = tree.args.zipWithConserve(mt.paramInfos)(typedExpr(_, _)).asInstanceOf[List[Tree]] assignType(untpd.cpy.Apply(tree)(fun, args), fun, args) case _ => super.handleUnexpectedFunType(tree, fun) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 93a534f6b..717429848 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -318,9 +318,9 @@ trait TypeAssigner { def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = { val ownType = fn.tpe.widen match { case fntpe: MethodType => - if (sameLength(fntpe.paramTypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes) + if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes) else - errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramTypes.length}, found: ${args.length}", tree.pos) + errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) case t => errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos) } @@ -368,7 +368,7 @@ trait TypeAssigner { val gaps = gapBuf.toList pt.derivedPolyType( gaps.map(paramNames), - gaps.map(idx => transform(pt.paramBounds(idx)).bounds), + gaps.map(idx => transform(pt.paramInfos(idx)).bounds), resultType1) } } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 68ff7579f..5e845a807 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -741,8 +741,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit calleeType.widen match { case mtpe: MethodType => val pos = params indexWhere (_.name == param.name) - if (pos < mtpe.paramTypes.length) { - val ptype = mtpe.paramTypes(pos) + if (pos < mtpe.paramInfos.length) { + val ptype = mtpe.paramInfos(pos) if (isFullyDefined(ptype, ForceDegree.noBottom)) return ptype } case _ => @@ -1809,12 +1809,12 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit errorTree(tree, em"""none of the ${err.overloadedAltsStr(altDenots)} |match $expectedStr""") - def hasEmptyParams(denot: SingleDenotation) = denot.info.paramTypess == ListOfNil + def hasEmptyParams(denot: SingleDenotation) = denot.info.paramInfoss == ListOfNil pt match { case pt: FunProto => tryInsertApplyOrImplicit(tree, pt)(noMatches) case _ => - if (altDenots exists (_.info.paramTypess == ListOfNil)) + if (altDenots exists (_.info.paramInfoss == ListOfNil)) typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt) else noMatches @@ -1886,7 +1886,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit adaptInterpolated(tree.withType(wtp.resultType), pt, original) case wtp: ImplicitMethodType if constrainResult(wtp, followAlias(pt)) => val tvarsToInstantiate = tvarsInParams(tree) - wtp.paramTypes.foreach(instantiateSelected(_, tvarsToInstantiate)) + wtp.paramInfos.foreach(instantiateSelected(_, tvarsToInstantiate)) val constr = ctx.typerState.constraint def addImplicitArgs(implicit ctx: Context) = { val errors = new mutable.ListBuffer[() => String] @@ -1898,7 +1898,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit for (err <- errors) ctx.error(err(), tree.pos.endPos) tree.withType(wtp.resultType) } - val args = (wtp.paramNames, wtp.paramTypes).zipped map { (pname, formal) => + val args = (wtp.paramNames, wtp.paramInfos).zipped map { (pname, formal) => def implicitArgError(msg: String => String) = errors += (() => msg(em"parameter $pname of $methodStr")) if (errors.nonEmpty) EmptyTree @@ -1941,11 +1941,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit // prioritize method parameter types as parameter types of the eta-expanded closure 0 else defn.functionArity(pt) - else if (pt eq AnyFunctionProto) wtp.paramTypes.length + else if (pt eq AnyFunctionProto) wtp.paramInfos.length else -1 if (arity >= 0 && !tree.symbol.isConstructor) typed(etaExpand(tree, wtp, arity), pt) - else if (wtp.paramTypes.isEmpty) + else if (wtp.paramInfos.isEmpty) adaptInterpolated(tpd.Apply(tree, Nil), pt, EmptyTree) else if (wtp.isImplicit) err.typeMismatch(tree, pt) diff --git a/compiler/src/dotty/tools/dotc/typer/Variances.scala b/compiler/src/dotty/tools/dotc/typer/Variances.scala index c2a75ee0e..83ac23f7e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Variances.scala +++ b/compiler/src/dotty/tools/dotc/typer/Variances.scala @@ -80,7 +80,7 @@ object Variances { case tp: RecType => varianceInType(tp.parent)(tparam) case tp: MethodType => - flip(varianceInTypes(tp.paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam) + flip(varianceInTypes(tp.paramInfos)(tparam)) & varianceInType(tp.resultType)(tparam) case ExprType(restpe) => varianceInType(restpe)(tparam) case tp @ HKApply(tycon, args) => @@ -95,7 +95,7 @@ object Variances { } varianceInArgs(varianceInType(tycon)(tparam), args, tycon.typeParams) case tp: PolyType => - flip(varianceInTypes(tp.paramBounds)(tparam)) & varianceInType(tp.resultType)(tparam) + flip(varianceInTypes(tp.paramInfos)(tparam)) & varianceInType(tp.resultType)(tparam) case AnnotatedType(tp, annot) => varianceInType(tp)(tparam) & varianceInAnnot(annot)(tparam) case tp: AndOrType => -- cgit v1.2.3 From 5811755f91d2bd501124922c0348923b430f0c49 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 16 Mar 2017 18:52:37 +0100 Subject: ParamType refactorings Trying to bring PolyTypes closer to TypeLambdas --- compiler/src/dotty/tools/dotc/core/Types.scala | 147 +++++++++++---------- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../dotty/tools/dotc/printing/PlainPrinter.scala | 4 +- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 2 +- 4 files changed, 78 insertions(+), 77 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 60d77446d..af37f6b6c 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2324,12 +2324,14 @@ object Types { * Proxy (hk) | HKTermLambda | HKTypeLambda * Ground (*) | MethodType | PolyType */ - trait LambdaType[PInfo <: Type] extends BindingType with MethodOrPoly { - def paramNames: List[TermName] + trait LambdaType[N <: Name, PInfo <: Type] extends BindingType with MethodOrPoly { + type This <: LambdaType[N, PInfo] + + def paramNames: List[N] def paramInfos: List[PInfo] def resType: Type - def newLikeThis(paramNames: List[Name], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): LambdaType[PInfo] - def newParamRef(n: Int): ParamRef[PInfo] + def newLikeThis(paramNames: List[N], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): LambdaType[N, PInfo] + def newParamRef(n: Int): ParamRef[N, This] override def resultType(implicit ctx: Context) = resType @@ -2339,20 +2341,20 @@ object Types { final def isTypeLambda = paramNames.head.isTypeName final def isHigherKinded = isInstanceOf[TypeProxy] - lazy val paramRefs: List[ParamRef[PInfo]] = paramNames.indices.toList.map(newParamRef) + lazy val paramRefs: List[ParamRef[N, This]] = paramNames.indices.toList.map(newParamRef) def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = if (isDependent) resultType.substParams(this, argTypes) else resultType - def derivedLambdaType(paramNames: List[Name] = this.paramNames, + def derivedLambdaType(paramNames: List[N] = this.paramNames, paramInfos: List[PInfo] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this else newLikeThis(paramNames, paramInfos, resType) override def equals(that: Any) = that match { - case that: LambdaType[_] => + case that: LambdaType[_, _] => this.paramNames == that.paramNames && this.paramInfos == that.paramInfos && this.resType == that.resType @@ -2361,8 +2363,11 @@ object Types { } } - trait LambdaOverTerms extends LambdaType[Type] { thisLambdaType => + trait LambdaOverTerms extends LambdaType[TermName, Type] { thisLambdaType => import LambdaOverTerms._ + type This = LambdaOverTerms + + def paramNames: List[TermName] override def resultType(implicit ctx: Context): Type = if (dependencyStatus == FalseDeps) { // dealias all false dependencies @@ -2395,7 +2400,7 @@ object Types { if (status == TrueDeps) status else tp match { - case ParamRef(`thisLambdaType`, _) => TrueDeps + case ParamRef(binder, _) if binder eq thisLambdaType => TrueDeps case tp: TypeRef => val status1 = foldOver(status, tp) tp.info match { // follow type alias to avoid dependency @@ -2452,10 +2457,7 @@ object Types { */ def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps - def newParamRef(n: Int): ParamRef[Type] = new TermParamRef(this, n) - } - - trait LambdaOverTypes extends LambdaType[TypeBounds] { thisLambdaType => + def newParamRef(n: Int) = new TermParamRef(this, n) } object LambdaOverTerms { @@ -2468,6 +2470,8 @@ object Types { private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations } + type LambdaOverTypes = PolyType // (for now) + abstract case class MethodType(paramNames: List[TermName])( paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) @@ -2491,8 +2495,8 @@ object Types { resType: Type = this.resType)(implicit ctx: Context) = derivedLambdaType(paramNames, paramInfos, resType) - def newLikeThis(paramNames: List[Name], paramInfos: List[Type], resType: Type)(implicit ctx: Context): MethodType = - companion(paramNames.asInstanceOf[List[TermName]])( + def newLikeThis(paramNames: List[TermName], paramInfos: List[Type], resType: Type)(implicit ctx: Context): MethodType = + companion(paramNames)( x => paramInfos.mapConserve(_.subst(this, x)), x => resType.subst(this, x)) @@ -2526,7 +2530,7 @@ object Types { override protected def prefixString = "ImplicitMethodType" } - abstract class LambdaTypeCompanion[PInfo <: Type, LT <: LambdaType[PInfo]] { + abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType[N, PInfo]] { def apply(paramNames: List[TermName])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT def apply(paramNames: List[TermName], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = apply(paramNames)(_ => paramInfos, _ => resultType) @@ -2536,7 +2540,7 @@ object Types { apply(nme.syntheticParamNames(paramInfos.length), paramInfos, resultType) } - abstract class MethodTypeCompanion extends LambdaTypeCompanion[Type, MethodType] { + abstract class MethodTypeCompanion extends LambdaTypeCompanion[TermName, Type, MethodType] { /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters. */ @@ -2572,7 +2576,7 @@ object Types { if (Config.checkMethodTypes) for ((paramInfo, idx) <- mt.paramInfos.zipWithIndex) paramInfo.foreachPart { - case ParamRef(`mt`, j) => assert(j < idx, mt) + case ParamRef(binder, j) if binder eq mt => assert(j < idx, mt) case _ => } mt @@ -2635,7 +2639,9 @@ object Types { */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends CachedProxyType with BindingType with MethodOrPoly { + extends CachedProxyType with LambdaType[TypeName, TypeBounds] { + + type This = PolyType /** The bounds of the type parameters */ val paramInfos: List[TypeBounds] = paramInfosExp(this) @@ -2648,18 +2654,15 @@ object Types { protected def computeSignature(implicit ctx: Context) = resultSignature - /** PolyParam references to all type parameters of this type */ - lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _)) - lazy val typeParams: List[LambdaParam] = paramNames.indices.toList.map(new LambdaParam(this, _)) override def resultType(implicit ctx: Context) = resType override def underlying(implicit ctx: Context) = resType - /** Instantiate result type by substituting parameters with given arguments */ - final def instantiate(argTypes: List[Type])(implicit ctx: Context): Type = - resultType.substParams(this, argTypes) + def isDependent(implicit ctx: Context) = true + def isParamDependent(implicit ctx: Context) = true + def newParamRef(n: Int) = PolyParam(this, n) /** Instantiate parameter bounds by substituting parameters with given arguments */ final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] = @@ -2728,6 +2731,11 @@ object Types { override def computeHash = doHash(paramNames, resType, paramInfos) } + object PolyParam { + def apply(pt: PolyType, n: Int) = new TypeParamRef(pt, n) + def unapply(poly: PolyParam) = Some(poly.binder, poly.paramNum) + } + object PolyType { def apply(paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], @@ -2844,48 +2852,24 @@ object Types { def paramName: Name } - abstract case class ParamRef[PInfo <: Type](binder: LambdaType[PInfo], paramNum: Int) extends ParamType { - type BT = LambdaType[PInfo] + abstract case class ParamRef[N <: Name, LT <: LambdaType[N, _ <: Type]] + (binder: LT, paramNum: Int) extends ParamType { + type BT = LT def paramName = binder.paramNames(paramNum) - override def underlying(implicit ctx: Context): Type = binder.paramInfos(paramNum) - - // need to customize hashCode and equals to prevent infinite recursion for dep meth types. - override def computeHash = addDelta(binder.identityHash, paramNum) - override def equals(that: Any) = that match { - case that: ParamRef[_] => - (this.binder eq that.binder) && this.paramNum == that.paramNum - case _ => - false - } - - override def toString = s"ParamRef($paramName)" - } - - class TermParamRef(binder: LambdaType[Type], paramNum: Int) - extends ParamRef[Type](binder, paramNum) with SingletonType { - def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum) - } - - object TermParamRef { - def apply(binder: LambdaType[Type], paramNum: Int)(implicit ctx: Context): TermParamRef = { - assertUnerased() - new TermParamRef(binder, paramNum) + override def underlying(implicit ctx: Context): Type = { + val infos = binder.paramInfos + if (infos == null) NoType // this can happen if the referenced generic type is not initialized yet + else infos(paramNum) } - } - - /** TODO Some docs would be nice here! */ - case class PolyParam(binder: PolyType, paramNum: Int) extends ParamType { - type BT = PolyType - def copyBoundType(bt: BT) = PolyParam(bt, paramNum) /** Looking only at the structure of `bound`, is one of the following true? * - fromBelow and param <:< bound * - !fromBelow and param >:> bound */ def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match { - case bound: PolyParam => bound == this + case bound: ParamRef[_, _] => bound == this case bound: AndOrType => def occ1 = occursIn(bound.tp1, fromBelow) def occ2 = occursIn(bound.tp2, fromBelow) @@ -2893,30 +2877,47 @@ object Types { case _ => false } - def paramName = binder.paramNames(paramNum) - - override def underlying(implicit ctx: Context): Type = { - val bounds = binder.paramInfos - if (bounds == null) NoType // this can happen if the referenced generic type is not initialized yet - else bounds(paramNum) + override def computeHash = doHash(paramNum, binder.identityHash) + override def equals(that: Any) = that match { + case that: ParamRef[_, _] => + (this.binder eq that.binder) && this.paramNum == that.paramNum + case _ => + false } - // no customized hashCode/equals needed because cycle is broken in PolyType + override def toString = - try s"PolyParam($paramName)" + try s"ParamRef($paramName)" catch { - case ex: IndexOutOfBoundsException => s"PolyParam()" + case ex: IndexOutOfBoundsException => s"ParamRef()" } + } - override def computeHash = doHash(paramNum, binder.identityHash) + class TermParamRef(binder: LambdaOverTerms, paramNum: Int) + extends ParamRef[TermName, LambdaOverTerms](binder, paramNum) with SingletonType { + def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum) + } - override def equals(that: Any) = that match { - case that: PolyParam => - (this.binder eq that.binder) && this.paramNum == that.paramNum - case _ => - false + object TermParamRef { + def apply(binder: LambdaOverTerms, paramNum: Int)(implicit ctx: Context): TermParamRef = { + assertUnerased() + new TermParamRef(binder, paramNum) } } + class TypeParamRef(binder: LambdaOverTypes, paramNum: Int) + extends ParamRef[TypeName, LambdaOverTypes](binder, paramNum) { + def copyBoundType(bt: BT) = new TypeParamRef(bt, paramNum) + } + + object TypeParamRef { + def apply(binder: LambdaOverTypes, paramNum: Int)(implicit ctx: Context): TypeParamRef = { + assertUnerased() + new TypeParamRef(binder, paramNum) + } + } + + type PolyParam = TypeParamRef + /** a self-reference to an enclosing recursive type. */ case class RecThis(binder: RecType) extends BoundType with SingletonType { type BT = RecType @@ -3860,7 +3861,7 @@ object Types { apply(x, tp.tref) case tp: ConstantType => apply(x, tp.underlying) - case tp: ParamRef[_] => + case tp: ParamRef[_, _] => apply(x, tp.underlying) case tp: PolyParam => apply(x, tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 8801eb19b..fc697bb4a 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -266,7 +266,7 @@ class TreePickler(pickler: TastyPickler) { case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) case _ => assert(false, s"orphan poly parameter: $tpe") } - case tpe: ParamRef[_] => + case tpe: ParamRef[_, _] => assert(pickleParamType(tpe), s"orphan method parameter: $tpe") case tpe: LazyRef => pickleType(tpe.ref) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index d6b7adffe..f32d5294b 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -183,7 +183,7 @@ class PlainPrinter(_ctx: Context) extends Printer { toTextGlobal(tp.resultType) } case tp: PolyParam => - polyParamNameString(tp) ~ polyHash(tp.binder) + polyParamNameString(tp) ~ lambdaHash(tp.binder) case AnnotatedType(tpe, annot) => toTextLocal(tpe) ~ " " ~ toText(annot) case HKApply(tycon, args) => @@ -217,7 +217,7 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def simpleNameString(sym: Symbol): String = nameString(sym.name) /** If -uniqid is set, the hashcode of the polytype, after a # */ - protected def polyHash(pt: PolyType): Text = + protected def lambdaHash(pt: LambdaType[_, _]): Text = if (ctx.settings.uniqid.value) "#" + pt.hashCode else "" /** If -uniqid is set, the unique id of symbol, after a # */ diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 2d5b1ff16..011c1fccb 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -256,7 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverse(tp.underlying) case tp: ConstantType => traverse(tp.underlying) - case tp: ParamRef[_] => + case tp: ParamRef[_, _] => traverse(tp.underlying) case tp: PolyParam => traverse(tp.underlying) -- cgit v1.2.3 From e6abcfc0d8009210cef8b78d14c13ddab267d921 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 16 Mar 2017 19:06:14 +0100 Subject: Get rid of Name parameter for LambdaType and ParamRef Use an abstract type instead. --- compiler/src/dotty/tools/dotc/core/Types.scala | 50 +++++++++++++--------- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../dotty/tools/dotc/printing/PlainPrinter.scala | 2 +- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 2 +- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index af37f6b6c..226399ed3 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2324,14 +2324,16 @@ object Types { * Proxy (hk) | HKTermLambda | HKTypeLambda * Ground (*) | MethodType | PolyType */ - trait LambdaType[N <: Name, PInfo <: Type] extends BindingType with MethodOrPoly { - type This <: LambdaType[N, PInfo] + trait LambdaType[PInfo <: Type] extends BindingType with MethodOrPoly { self => + type ThisName <: Name + type This <: LambdaType[PInfo] - def paramNames: List[N] + def paramNames: List[ThisName] def paramInfos: List[PInfo] def resType: Type - def newLikeThis(paramNames: List[N], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): LambdaType[N, PInfo] - def newParamRef(n: Int): ParamRef[N, This] + def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type) + (implicit ctx: Context): LambdaType[PInfo] { type ThisName = self.ThisName } + def newParamRef(n: Int): ParamRef[This] override def resultType(implicit ctx: Context) = resType @@ -2341,20 +2343,20 @@ object Types { final def isTypeLambda = paramNames.head.isTypeName final def isHigherKinded = isInstanceOf[TypeProxy] - lazy val paramRefs: List[ParamRef[N, This]] = paramNames.indices.toList.map(newParamRef) + lazy val paramRefs: List[ParamRef[This]] = paramNames.indices.toList.map(newParamRef) def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = if (isDependent) resultType.substParams(this, argTypes) else resultType - def derivedLambdaType(paramNames: List[N] = this.paramNames, + def derivedLambdaType(paramNames: List[ThisName] = this.paramNames, paramInfos: List[PInfo] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this else newLikeThis(paramNames, paramInfos, resType) override def equals(that: Any) = that match { - case that: LambdaType[_, _] => + case that: LambdaType[_] => this.paramNames == that.paramNames && this.paramInfos == that.paramInfos && this.resType == that.resType @@ -2363,8 +2365,9 @@ object Types { } } - trait LambdaOverTerms extends LambdaType[TermName, Type] { thisLambdaType => + trait LambdaOverTerms extends LambdaType[Type] { thisLambdaType => import LambdaOverTerms._ + type ThisName = TermName type This = LambdaOverTerms def paramNames: List[TermName] @@ -2530,17 +2533,20 @@ object Types { override protected def prefixString = "ImplicitMethodType" } - abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType[N, PInfo]] { - def apply(paramNames: List[TermName])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT - def apply(paramNames: List[TermName], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = + abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType[PInfo]] { + def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT + def syntheticParamNames(n: Int): List[N] + def apply(paramNames: List[N], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = apply(paramNames)(_ => paramInfos, _ => resultType) def apply(paramInfos: List[PInfo])(resultTypeExp: LT => Type)(implicit ctx: Context): LT = - apply(nme.syntheticParamNames(paramInfos.length))(_ => paramInfos, resultTypeExp) + apply(syntheticParamNames(paramInfos.length))(_ => paramInfos, resultTypeExp) def apply(paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = - apply(nme.syntheticParamNames(paramInfos.length), paramInfos, resultType) + apply(syntheticParamNames(paramInfos.length), paramInfos, resultType) } abstract class MethodTypeCompanion extends LambdaTypeCompanion[TermName, Type, MethodType] { + def syntheticParamNames(n: Int): List[TermName] = nme.syntheticParamNames(n) + /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters. */ @@ -2584,6 +2590,7 @@ object Types { } object MethodType extends MethodTypeCompanion { + def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = checkValid(unique(new CachedMethodType(paramNames)(paramInfosExp, resultTypeExp))) } @@ -2639,8 +2646,9 @@ object Types { */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends CachedProxyType with LambdaType[TypeName, TypeBounds] { + extends CachedProxyType with LambdaType[TypeBounds] { + type ThisName = TypeName type This = PolyType /** The bounds of the type parameters */ @@ -2852,7 +2860,7 @@ object Types { def paramName: Name } - abstract case class ParamRef[N <: Name, LT <: LambdaType[N, _ <: Type]] + abstract case class ParamRef[LT <: LambdaType[_ <: Type]] (binder: LT, paramNum: Int) extends ParamType { type BT = LT @@ -2869,7 +2877,7 @@ object Types { * - !fromBelow and param >:> bound */ def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match { - case bound: ParamRef[_, _] => bound == this + case bound: ParamRef[_] => bound == this case bound: AndOrType => def occ1 = occursIn(bound.tp1, fromBelow) def occ2 = occursIn(bound.tp2, fromBelow) @@ -2879,7 +2887,7 @@ object Types { override def computeHash = doHash(paramNum, binder.identityHash) override def equals(that: Any) = that match { - case that: ParamRef[_, _] => + case that: ParamRef[_] => (this.binder eq that.binder) && this.paramNum == that.paramNum case _ => false @@ -2893,7 +2901,7 @@ object Types { } class TermParamRef(binder: LambdaOverTerms, paramNum: Int) - extends ParamRef[TermName, LambdaOverTerms](binder, paramNum) with SingletonType { + extends ParamRef[LambdaOverTerms](binder, paramNum) with SingletonType { def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum) } @@ -2905,7 +2913,7 @@ object Types { } class TypeParamRef(binder: LambdaOverTypes, paramNum: Int) - extends ParamRef[TypeName, LambdaOverTypes](binder, paramNum) { + extends ParamRef[LambdaOverTypes](binder, paramNum) { def copyBoundType(bt: BT) = new TypeParamRef(bt, paramNum) } @@ -3861,7 +3869,7 @@ object Types { apply(x, tp.tref) case tp: ConstantType => apply(x, tp.underlying) - case tp: ParamRef[_, _] => + case tp: ParamRef[_] => apply(x, tp.underlying) case tp: PolyParam => apply(x, tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index fc697bb4a..8801eb19b 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -266,7 +266,7 @@ class TreePickler(pickler: TastyPickler) { case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) case _ => assert(false, s"orphan poly parameter: $tpe") } - case tpe: ParamRef[_, _] => + case tpe: ParamRef[_] => assert(pickleParamType(tpe), s"orphan method parameter: $tpe") case tpe: LazyRef => pickleType(tpe.ref) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index f32d5294b..8232f31db 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -217,7 +217,7 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def simpleNameString(sym: Symbol): String = nameString(sym.name) /** If -uniqid is set, the hashcode of the polytype, after a # */ - protected def lambdaHash(pt: LambdaType[_, _]): Text = + protected def lambdaHash(pt: LambdaType[_]): Text = if (ctx.settings.uniqid.value) "#" + pt.hashCode else "" /** If -uniqid is set, the unique id of symbol, after a # */ diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 011c1fccb..2d5b1ff16 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -256,7 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverse(tp.underlying) case tp: ConstantType => traverse(tp.underlying) - case tp: ParamRef[_, _] => + case tp: ParamRef[_] => traverse(tp.underlying) case tp: PolyParam => traverse(tp.underlying) -- cgit v1.2.3 From 71daa0342120d2414c840a1dda2eae5e676aece2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 11:20:11 +0100 Subject: Disable -strict when compiling dotty. It seems we need a more refined way to deal with non-variant variables in pattern matches. See branch change-patmat-undet for a WIP. For the moment we disable -strict to be able to compile latest version of dotty. --- compiler/test/dotc/tests.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index 1c80767ee..cc860c29e 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -98,8 +98,8 @@ class tests extends CompilerTest { val typerDir = dotcDir + "typer/" val libDir = "../library/src/" - def dottyBootedLib = compileDir(libDir, ".", List("-deep", "-Ycheck-reentrant", "-strict") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument - def dottyDependsOnBootedLib = compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant", "-strict") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument + def dottyBootedLib = compileDir(libDir, ".", List("-deep", "-Ycheck-reentrant") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument + def dottyDependsOnBootedLib = compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument @Before def cleanup(): Unit = { // remove class files from stdlib and tests compilation @@ -354,7 +354,7 @@ class tests extends CompilerTest { val logging = if (false) List("-Ylog-classpath", "-verbose") else Nil val opt = List("-priorityclasspath", defaultOutputDir) ++ logging // first compile dotty - compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant", "-strict") ++ logging)(allowDeepSubtypes) + compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant") ++ logging)(allowDeepSubtypes) compileDir(libDir, "dotty", "-deep" :: opt) compileDir(libDir, "scala", "-deep" :: opt) -- cgit v1.2.3 From c7718516fdad609625215f4fb1c7cffe27db3af5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 11:29:07 +0100 Subject: Remove parameter from lambda type --- compiler/src/dotty/tools/dotc/core/Types.scala | 19 +++++++++++-------- .../src/dotty/tools/dotc/printing/PlainPrinter.scala | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 226399ed3..0642ca8d4 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2324,15 +2324,16 @@ object Types { * Proxy (hk) | HKTermLambda | HKTypeLambda * Ground (*) | MethodType | PolyType */ - trait LambdaType[PInfo <: Type] extends BindingType with MethodOrPoly { self => + trait LambdaType extends BindingType with MethodOrPoly { self => type ThisName <: Name - type This <: LambdaType[PInfo] + type PInfo <: Type + type This <: LambdaType{type PInfo = self.PInfo} def paramNames: List[ThisName] def paramInfos: List[PInfo] def resType: Type def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type) - (implicit ctx: Context): LambdaType[PInfo] { type ThisName = self.ThisName } + (implicit ctx: Context): LambdaType { type ThisName = self.ThisName; type PInfo = self.PInfo } def newParamRef(n: Int): ParamRef[This] override def resultType(implicit ctx: Context) = resType @@ -2356,7 +2357,7 @@ object Types { else newLikeThis(paramNames, paramInfos, resType) override def equals(that: Any) = that match { - case that: LambdaType[_] => + case that: LambdaType => this.paramNames == that.paramNames && this.paramInfos == that.paramInfos && this.resType == that.resType @@ -2365,9 +2366,10 @@ object Types { } } - trait LambdaOverTerms extends LambdaType[Type] { thisLambdaType => + trait LambdaOverTerms extends LambdaType { thisLambdaType => import LambdaOverTerms._ type ThisName = TermName + type PInfo = Type type This = LambdaOverTerms def paramNames: List[TermName] @@ -2533,7 +2535,7 @@ object Types { override protected def prefixString = "ImplicitMethodType" } - abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType[PInfo]] { + abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] { def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT def syntheticParamNames(n: Int): List[N] def apply(paramNames: List[N], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = @@ -2646,9 +2648,10 @@ object Types { */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends CachedProxyType with LambdaType[TypeBounds] { + extends CachedProxyType with LambdaType { type ThisName = TypeName + type PInfo = TypeBounds type This = PolyType /** The bounds of the type parameters */ @@ -2860,7 +2863,7 @@ object Types { def paramName: Name } - abstract case class ParamRef[LT <: LambdaType[_ <: Type]] + abstract case class ParamRef[LT <: LambdaType] (binder: LT, paramNum: Int) extends ParamType { type BT = LT diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 8232f31db..a4f9921db 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -217,7 +217,7 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def simpleNameString(sym: Symbol): String = nameString(sym.name) /** If -uniqid is set, the hashcode of the polytype, after a # */ - protected def lambdaHash(pt: LambdaType[_]): Text = + protected def lambdaHash(pt: LambdaType): Text = if (ctx.settings.uniqid.value) "#" + pt.hashCode else "" /** If -uniqid is set, the unique id of symbol, after a # */ -- cgit v1.2.3 From 30af0b52e4e5b185ef84496559dc44c8d93d6357 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 12:10:32 +0100 Subject: Disable -strict when compiling dotty. It seems we need a more refined way to deal with non-variant variables in pattern matches. See branch change-patmat-undet for a WIP. For the moment we disable -strict to be able to compile latest version of dotty. (reverted from commit c8fe830f8a382eb965c2231064fa286ee8f0a4ec) --- compiler/test/dotc/tests.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index cc860c29e..1c80767ee 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -98,8 +98,8 @@ class tests extends CompilerTest { val typerDir = dotcDir + "typer/" val libDir = "../library/src/" - def dottyBootedLib = compileDir(libDir, ".", List("-deep", "-Ycheck-reentrant") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument - def dottyDependsOnBootedLib = compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument + def dottyBootedLib = compileDir(libDir, ".", List("-deep", "-Ycheck-reentrant", "-strict") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument + def dottyDependsOnBootedLib = compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant", "-strict") ::: defaultOptions)(allowDeepSubtypes) // note the -deep argument @Before def cleanup(): Unit = { // remove class files from stdlib and tests compilation @@ -354,7 +354,7 @@ class tests extends CompilerTest { val logging = if (false) List("-Ylog-classpath", "-verbose") else Nil val opt = List("-priorityclasspath", defaultOutputDir) ++ logging // first compile dotty - compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant") ++ logging)(allowDeepSubtypes) + compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant", "-strict") ++ logging)(allowDeepSubtypes) compileDir(libDir, "dotty", "-deep" :: opt) compileDir(libDir, "scala", "-deep" :: opt) -- cgit v1.2.3 From 2b5d1a80023f5676f5a97f0c56919c1f04f7ce2f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 13:17:49 +0100 Subject: Refactor ParamRef so that no type params are needed --- compiler/src/dotty/tools/dotc/core/Types.scala | 76 ++++++++-------------- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 2 +- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- 4 files changed, 31 insertions(+), 51 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 0642ca8d4..5629668c1 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2334,7 +2334,7 @@ object Types { def resType: Type def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type) (implicit ctx: Context): LambdaType { type ThisName = self.ThisName; type PInfo = self.PInfo } - def newParamRef(n: Int): ParamRef[This] + def newParamRef(n: Int): ParamRef override def resultType(implicit ctx: Context) = resType @@ -2344,7 +2344,7 @@ object Types { final def isTypeLambda = paramNames.head.isTypeName final def isHigherKinded = isInstanceOf[TypeProxy] - lazy val paramRefs: List[ParamRef[This]] = paramNames.indices.toList.map(newParamRef) + lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef) def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = if (isDependent) resultType.substParams(this, argTypes) @@ -2405,7 +2405,7 @@ object Types { if (status == TrueDeps) status else tp match { - case ParamRef(binder, _) if binder eq thisLambdaType => TrueDeps + case TermParamRef(`thisLambdaType`, _) => TrueDeps case tp: TypeRef => val status1 = foldOver(status, tp) tp.info match { // follow type alias to avoid dependency @@ -2462,7 +2462,7 @@ object Types { */ def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps - def newParamRef(n: Int) = new TermParamRef(this, n) + def newParamRef(n: Int) = TermParamRef(this, n) } object LambdaOverTerms { @@ -2584,7 +2584,7 @@ object Types { if (Config.checkMethodTypes) for ((paramInfo, idx) <- mt.paramInfos.zipWithIndex) paramInfo.foreachPart { - case ParamRef(binder, j) if binder eq mt => assert(j < idx, mt) + case TermParamRef(`mt`, j) => assert(j < idx, mt) case _ => } mt @@ -2850,11 +2850,7 @@ object Types { abstract class BoundType extends CachedProxyType with ValueType { type BT <: Type - def binder: BT - // Dotty deviation: copyBoundType was copy, but - // dotty generates copy methods always automatically, and therefore - // does not accept same-named method definitions in subclasses. - // Scala2x, on the other hand, requires them (not sure why!) + val binder: BT def copyBoundType(bt: BT): Type } @@ -2863,11 +2859,9 @@ object Types { def paramName: Name } - abstract case class ParamRef[LT <: LambdaType] - (binder: LT, paramNum: Int) extends ParamType { - type BT = LT - - def paramName = binder.paramNames(paramNum) + abstract class ParamRef extends ParamType { + type BT <: LambdaType + def paramName: binder.ThisName = binder.paramNames(paramNum) override def underlying(implicit ctx: Context): Type = { val infos = binder.paramInfos @@ -2875,22 +2869,9 @@ object Types { else infos(paramNum) } - /** Looking only at the structure of `bound`, is one of the following true? - * - fromBelow and param <:< bound - * - !fromBelow and param >:> bound - */ - def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match { - case bound: ParamRef[_] => bound == this - case bound: AndOrType => - def occ1 = occursIn(bound.tp1, fromBelow) - def occ2 = occursIn(bound.tp2, fromBelow) - if (fromBelow == bound.isAnd) occ1 && occ2 else occ1 || occ2 - case _ => false - } - override def computeHash = doHash(paramNum, binder.identityHash) override def equals(that: Any) = that match { - case that: ParamRef[_] => + case that: ParamRef => (this.binder eq that.binder) && this.paramNum == that.paramNum case _ => false @@ -2903,27 +2884,26 @@ object Types { } } - class TermParamRef(binder: LambdaOverTerms, paramNum: Int) - extends ParamRef[LambdaOverTerms](binder, paramNum) with SingletonType { - def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum) + case class TermParamRef(binder: LambdaOverTerms, paramNum: Int) extends ParamRef { + type BT = LambdaOverTerms + def copyBoundType(bt: BT) = TermParamRef(bt, paramNum) } - object TermParamRef { - def apply(binder: LambdaOverTerms, paramNum: Int)(implicit ctx: Context): TermParamRef = { - assertUnerased() - new TermParamRef(binder, paramNum) - } - } - - class TypeParamRef(binder: LambdaOverTypes, paramNum: Int) - extends ParamRef[LambdaOverTypes](binder, paramNum) { - def copyBoundType(bt: BT) = new TypeParamRef(bt, paramNum) - } + case class TypeParamRef(binder: LambdaOverTypes, paramNum: Int) extends ParamRef { + type BT = LambdaOverTypes + def copyBoundType(bt: BT) = TypeParamRef(bt, paramNum) - object TypeParamRef { - def apply(binder: LambdaOverTypes, paramNum: Int)(implicit ctx: Context): TypeParamRef = { - assertUnerased() - new TypeParamRef(binder, paramNum) + /** Looking only at the structure of `bound`, is one of the following true? + * - fromBelow and param <:< bound + * - !fromBelow and param >:> bound + */ + def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match { + case bound: ParamRef => bound == this + case bound: AndOrType => + def occ1 = occursIn(bound.tp1, fromBelow) + def occ2 = occursIn(bound.tp2, fromBelow) + if (fromBelow == bound.isAnd) occ1 && occ2 else occ1 || occ2 + case _ => false } } @@ -3872,7 +3852,7 @@ object Types { apply(x, tp.tref) case tp: ConstantType => apply(x, tp.underlying) - case tp: ParamRef[_] => + case tp: TermParamRef => apply(x, tp.underlying) case tp: PolyParam => apply(x, tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 8801eb19b..a9cd9be1d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -266,7 +266,7 @@ class TreePickler(pickler: TastyPickler) { case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) case _ => assert(false, s"orphan poly parameter: $tpe") } - case tpe: ParamRef[_] => + case tpe: TermParamRef => assert(pickleParamType(tpe), s"orphan method parameter: $tpe") case tpe: LazyRef => pickleType(tpe.ref) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 2d5b1ff16..d608dc7c4 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -256,7 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverse(tp.underlying) case tp: ConstantType => traverse(tp.underlying) - case tp: ParamRef[_] => + case tp: TermParamRef => traverse(tp.underlying) case tp: PolyParam => traverse(tp.underlying) diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 7406d1786..89e4f93e2 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -485,7 +485,7 @@ object ProtoTypes { case inst => wildApprox(inst, theMap, seen) } approxPoly - case ParamRef(mt, pnum) => + case TermParamRef(mt, pnum) => WildcardType(TypeBounds.upper(wildApprox(mt.paramInfos(pnum), theMap, seen))) case tp: TypeVar => wildApprox(tp.underlying, theMap, seen) -- cgit v1.2.3 From 70b3b90d686f3444e6b16cbf9deedc8aed0c62e8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 13:30:19 +0100 Subject: Rename PolyParam --> TypeParamRef --- compiler/src/dotty/tools/dotc/config/Config.scala | 2 +- compiler/src/dotty/tools/dotc/core/Constants.scala | 2 +- .../src/dotty/tools/dotc/core/Constraint.scala | 42 +++++----- .../dotty/tools/dotc/core/ConstraintHandling.scala | 36 ++++---- .../src/dotty/tools/dotc/core/Definitions.scala | 6 +- compiler/src/dotty/tools/dotc/core/Mode.scala | 2 +- .../dotty/tools/dotc/core/OrderingConstraint.scala | 98 +++++++++++----------- .../dotty/tools/dotc/core/TypeApplications.scala | 8 +- .../src/dotty/tools/dotc/core/TypeComparer.scala | 32 +++---- .../src/dotty/tools/dotc/core/TypeErasure.scala | 6 +- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 2 +- .../src/dotty/tools/dotc/core/TyperState.scala | 2 +- compiler/src/dotty/tools/dotc/core/Types.scala | 33 +++----- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- .../src/dotty/tools/dotc/printing/Formatting.scala | 10 +-- .../dotty/tools/dotc/printing/PlainPrinter.scala | 10 +-- .../dotty/tools/dotc/printing/RefinedPrinter.scala | 2 +- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 2 +- .../dotc/transform/FullParameterization.scala | 2 +- .../dotty/tools/dotc/transform/TreeChecker.scala | 2 +- .../src/dotty/tools/dotc/typer/Applications.scala | 2 +- .../dotty/tools/dotc/typer/ErrorReporting.scala | 4 +- .../src/dotty/tools/dotc/typer/Inferencing.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 2 +- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 20 ++--- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 4 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 28 files changed, 166 insertions(+), 173 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 903efd794..46b1896f1 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -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 diff --git a/compiler/src/dotty/tools/dotc/core/Constants.scala b/compiler/src/dotty/tools/dotc/core/Constants.scala index e8b27c0ba..ed388b7ec 100644 --- a/compiler/src/dotty/tools/dotc/core/Constants.scala +++ b/compiler/src/dotty/tools/dotc/core/Constants.scala @@ -169,7 +169,7 @@ 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 diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala index 50136a26c..fe14aa53c 100644 --- a/compiler/src/dotty/tools/dotc/core/Constraint.scala +++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala @@ -14,9 +14,9 @@ import config.Printers.constr * 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 + * - TypeParamRef The parameters of the constrained polytypes * - TypeVar Every constrained parameter might be associated with a TypeVar - * that has the PolyParam as origin. + * that has the TypeParamRef as origin. */ abstract class Constraint extends Showable { @@ -26,7 +26,7 @@ abstract class Constraint extends Showable { def contains(pt: PolyType): 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 @@ -34,43 +34,43 @@ abstract class Constraint extends Showable { /** 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`. @@ -90,18 +90,18 @@ 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 @@ -109,7 +109,7 @@ abstract class Constraint extends Showable { * 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 @@ -124,10 +124,10 @@ abstract class Constraint extends Showable { def domainPolys: List[PolyType] /** The polytype parameters constrained by this constraint */ - def domainParams: List[PolyParam] + 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. @@ -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 } diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 34662cbff..ab176b632 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -47,7 +47,7 @@ trait ConstraintHandling { */ protected var comparedPolyTypes: Set[PolyType] = Set.empty - private def addOneBound(param: PolyParam, bound: Type, isUpper: Boolean): Boolean = + private def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean): Boolean = !constraint.contains(param) || { def occursIn(bound: Type): Boolean = { val b = bound.dealias @@ -75,7 +75,7 @@ trait ConstraintHandling { * If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure * that `param >: bound`. */ - def narrowedBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): TypeBounds = { + def narrowedBound(param: TypeParamRef, bound: Type, isUpper: Boolean)(implicit ctx: Context): TypeBounds = { val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param) val saved = homogenizeArgs homogenizeArgs = Config.alignArgsInAnd @@ -85,7 +85,7 @@ trait ConstraintHandling { finally homogenizeArgs = saved } - protected def addUpperBound(param: PolyParam, bound: Type): Boolean = { + protected def addUpperBound(param: TypeParamRef, bound: Type): Boolean = { def description = i"constraint $param <: $bound to\n$constraint" if (bound.isRef(defn.NothingClass) && ctx.typerState.isGlobalCommittable) { def msg = s"!!! instantiated to Nothing: $param, constraint = ${constraint.show}" @@ -101,7 +101,7 @@ trait ConstraintHandling { res } - protected def addLowerBound(param: PolyParam, bound: Type): Boolean = { + protected def addLowerBound(param: TypeParamRef, bound: Type): Boolean = { def description = i"constraint $param >: $bound to\n$constraint" constr.println(i"adding $description") val upper = constraint.upper(param) @@ -112,7 +112,7 @@ trait ConstraintHandling { res } - protected def addLess(p1: PolyParam, p2: PolyParam): Boolean = { + protected def addLess(p1: TypeParamRef, p2: TypeParamRef): Boolean = { def description = i"ordering $p1 <: $p2 to\n$constraint" val res = if (constraint.isLess(p2, p1)) unify(p2, p1) @@ -133,7 +133,7 @@ trait ConstraintHandling { /** Make p2 = p1, transfer all bounds of p2 to p1 * @pre less(p1)(p2) */ - private def unify(p1: PolyParam, p2: PolyParam): Boolean = { + private def unify(p1: TypeParamRef, p2: TypeParamRef): Boolean = { constr.println(s"unifying $p1 $p2") assert(constraint.isLess(p1, p2)) val down = constraint.exclusiveLower(p2, p1) @@ -191,7 +191,7 @@ trait ConstraintHandling { * @return the instantiating type * @pre `param` is in the constraint's domain. */ - final def approximation(param: PolyParam, fromBelow: Boolean): Type = { + final def approximation(param: TypeParamRef, fromBelow: Boolean): Type = { val avoidParam = new TypeMap { override def stopAtStatic = true def apply(tp: Type) = mapOver { @@ -235,7 +235,7 @@ trait ConstraintHandling { * a lower bound instantiation can be a singleton type only if the upper bound * is also a singleton type. */ - def instanceType(param: PolyParam, fromBelow: Boolean): Type = { + def instanceType(param: TypeParamRef, fromBelow: Boolean): Type = { def upperBound = constraint.fullUpperBound(param) def isSingleton(tp: Type): Boolean = tp match { case tp: SingletonType => true @@ -301,7 +301,7 @@ trait ConstraintHandling { } /** The current bounds of type parameter `param` */ - final def bounds(param: PolyParam): TypeBounds = { + final def bounds(param: TypeParamRef): TypeBounds = { val e = constraint.entry(param) if (e.exists) e.bounds else param.binder.paramInfos(param.paramNum) } @@ -315,7 +315,7 @@ trait ConstraintHandling { checkPropagated(i"initialized $pt") { constraint = constraint.add(pt, tvars) pt.paramNames.indices.forall { i => - val param = PolyParam(pt, i) + val param = TypeParamRef(pt, i) val bounds = constraint.nonParamBounds(param) val lower = constraint.lower(param) val upper = constraint.upper(param) @@ -328,7 +328,7 @@ trait ConstraintHandling { } /** Can `param` be constrained with new bounds? */ - final def canConstrain(param: PolyParam): Boolean = + final def canConstrain(param: TypeParamRef): Boolean = !frozenConstraint && (constraint contains param) /** Add constraint `param <: bound` if `fromBelow` is false, `param >: bound` otherwise. @@ -338,7 +338,7 @@ trait ConstraintHandling { * not be AndTypes and lower bounds may not be OrTypes. This is assured by the * way isSubType is organized. */ - protected def addConstraint(param: PolyParam, bound: Type, fromBelow: Boolean): Boolean = { + protected def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean): Boolean = { def description = i"constr $param ${if (fromBelow) ">:" else "<:"} $bound:\n$constraint" //checkPropagated(s"adding $description")(true) // DEBUG in case following fails checkPropagated(s"added $description") { @@ -360,7 +360,7 @@ trait ConstraintHandling { if (comparedPolyTypes.nonEmpty) { val approx = new ApproximatingTypeMap { def apply(t: Type): Type = t match { - case t @ PolyParam(pt: PolyType, n) if comparedPolyTypes contains pt => + case t @ TypeParamRef(pt: PolyType, n) if comparedPolyTypes contains pt => val effectiveVariance = if (fromBelow) -variance else variance val bounds = pt.paramInfos(n) if (effectiveVariance > 0) bounds.lo @@ -374,7 +374,7 @@ trait ConstraintHandling { } else tp - def addParamBound(bound: PolyParam) = + def addParamBound(bound: TypeParamRef) = if (fromBelow) addLess(bound, param) else addLess(param, bound) /** Drop all constrained parameters that occur at the toplevel in `bound` and @@ -419,7 +419,7 @@ trait ConstraintHandling { else NoType case bound: TypeVar if constraint contains bound.origin => prune(bound.underlying) - case bound: PolyParam => + case bound: TypeParamRef => constraint.entry(bound) match { case NoType => pruneLambdaParams(bound) case _: TypeBounds => @@ -434,7 +434,7 @@ trait ConstraintHandling { } try bound match { - case bound: PolyParam if constraint contains bound => + case bound: TypeParamRef if constraint contains bound => addParamBound(bound) case _ => val pbound = prune(bound) @@ -446,7 +446,7 @@ trait ConstraintHandling { } /** Instantiate `param` to `tp` if the constraint stays satisfiable */ - protected def tryInstantiate(param: PolyParam, tp: Type): Boolean = { + protected def tryInstantiate(param: TypeParamRef, tp: Type): Boolean = { val saved = constraint constraint = if (addConstraint(param, tp, fromBelow = true) && @@ -461,7 +461,7 @@ trait ConstraintHandling { val saved = frozenConstraint frozenConstraint = true for (p <- constraint.domainParams) { - def check(cond: => Boolean, q: PolyParam, ordering: String, explanation: String): Unit = + def check(cond: => Boolean, q: TypeParamRef, ordering: String, explanation: String): Unit = assert(cond, i"propagation failure for $p $ordering $q: $explanation\n$msg") for (u <- constraint.upper(p)) check(bounds(p).hi <:< bounds(u).hi, u, "<:", "upper bound not propagated") diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 0c1d6521d..9360cabb1 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -242,7 +242,7 @@ class Definitions { lazy val Any_## = enterMethod(AnyClass, nme.HASHHASH, ExprType(IntType), Final) lazy val Any_getClass = enterMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final) lazy val Any_isInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final) - lazy val Any_asInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, PolyParam(_, 0), Final) + lazy val Any_asInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, TypeParamRef(_, 0), Final) def AnyMethods = List(Any_==, Any_!=, Any_equals, Any_hashCode, Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf) @@ -268,7 +268,7 @@ class Definitions { lazy val Object_eq = enterMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final) lazy val Object_ne = enterMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final) lazy val Object_synchronized = enterPolyMethod(ObjectClass, nme.synchronized_, 1, - pt => MethodType(List(PolyParam(pt, 0)), PolyParam(pt, 0)), Final) + pt => MethodType(List(TypeParamRef(pt, 0)), TypeParamRef(pt, 0)), Final) lazy val Object_clone = enterMethod(ObjectClass, nme.clone_, MethodType(Nil, ObjectType), Protected) lazy val Object_finalize = enterMethod(ObjectClass, nme.finalize_, MethodType(Nil, UnitType), Protected) lazy val Object_notify = enterMethod(ObjectClass, nme.notify_, MethodType(Nil, UnitType)) @@ -283,7 +283,7 @@ class Definitions { /** Dummy method needed by elimByName */ lazy val dummyApply = enterPolyMethod( OpsPackageClass, nme.dummyApply, 1, - pt => MethodType(List(FunctionOf(Nil, PolyParam(pt, 0))), PolyParam(pt, 0))) + pt => MethodType(List(FunctionOf(Nil, TypeParamRef(pt, 0))), TypeParamRef(pt, 0))) /** Method representing a throw */ lazy val throwMethod = enterMethod(OpsPackageClass, nme.THROWkw, diff --git a/compiler/src/dotty/tools/dotc/core/Mode.scala b/compiler/src/dotty/tools/dotc/core/Mode.scala index 406a84af6..c835f677e 100644 --- a/compiler/src/dotty/tools/dotc/core/Mode.scala +++ b/compiler/src/dotty/tools/dotc/core/Mode.scala @@ -34,7 +34,7 @@ object Mode { * context with typerstate and constraint. This is typically done when we * cache the eligibility of implicits. Caching needs to be done across different constraints. * Therefore, if TypevarsMissContext is set, subtyping becomes looser, and assumes - * that PolyParams can be sub- and supertypes of anything. See TypeComparer. + * that TypeParamRefs can be sub- and supertypes of anything. See TypeComparer. */ val TypevarsMissContext = newMode(4, "TypevarsMissContext") val CheckCyclic = newMode(5, "CheckCyclic") diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 3387f20e3..dbb952369 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -20,7 +20,7 @@ object OrderingConstraint { type ParamBounds = ArrayValuedMap[Type] /** The type of `OrderingConstraint#lowerMap`, `OrderingConstraint#upperMap` */ - type ParamOrdering = ArrayValuedMap[List[PolyParam]] + type ParamOrdering = ArrayValuedMap[List[TypeParamRef]] /** A new constraint with given maps */ private def newConstraint(boundsMap: ParamBounds, lowerMap: ParamOrdering, upperMap: ParamOrdering)(implicit ctx: Context) : OrderingConstraint = { @@ -68,7 +68,7 @@ object OrderingConstraint { } def update(prev: OrderingConstraint, current: OrderingConstraint, - param: PolyParam, entry: T)(implicit ctx: Context): OrderingConstraint = + param: TypeParamRef, entry: T)(implicit ctx: Context): OrderingConstraint = update(prev, current, param.binder, param.paramNum, entry) def map(prev: OrderingConstraint, current: OrderingConstraint, @@ -76,7 +76,7 @@ object OrderingConstraint { update(prev, current, poly, idx, f(apply(current, poly, idx))) def map(prev: OrderingConstraint, current: OrderingConstraint, - param: PolyParam, f: T => T)(implicit ctx: Context): OrderingConstraint = + param: TypeParamRef, f: T => T)(implicit ctx: Context): OrderingConstraint = map(prev, current, param.binder, param.paramNum, f) } @@ -88,18 +88,18 @@ object OrderingConstraint { def initial = NoType } - val lowerLens = new ConstraintLens[List[PolyParam]] { - def entries(c: OrderingConstraint, poly: PolyType): Array[List[PolyParam]] = + val lowerLens = new ConstraintLens[List[TypeParamRef]] { + def entries(c: OrderingConstraint, poly: PolyType): Array[List[TypeParamRef]] = c.lowerMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap.updated(poly, entries), c.upperMap) def initial = Nil } - val upperLens = new ConstraintLens[List[PolyParam]] { - def entries(c: OrderingConstraint, poly: PolyType): Array[List[PolyParam]] = + val upperLens = new ConstraintLens[List[TypeParamRef]] { + def entries(c: OrderingConstraint, poly: PolyType): Array[List[TypeParamRef]] = c.upperMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap, c.upperMap.updated(poly, entries)) def initial = Nil } @@ -141,7 +141,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, entries(paramCount(entries) + n) /** The `boundsMap` entry corresponding to `param` */ - def entry(param: PolyParam): Type = { + def entry(param: TypeParamRef): Type = { val entries = boundsMap(param.binder) if (entries == null) NoType else entries(param.paramNum) @@ -151,7 +151,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def contains(pt: PolyType): Boolean = boundsMap(pt) != null - def contains(param: PolyParam): Boolean = { + def contains(param: TypeParamRef): Boolean = { val entries = boundsMap(param.binder) entries != null && isBounds(entries(param.paramNum)) } @@ -167,43 +167,43 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ---------- Dependency handling ---------------------------------------------- - def lower(param: PolyParam): List[PolyParam] = lowerLens(this, param.binder, param.paramNum) - def upper(param: PolyParam): List[PolyParam] = upperLens(this, param.binder, param.paramNum) + def lower(param: TypeParamRef): List[TypeParamRef] = lowerLens(this, param.binder, param.paramNum) + def upper(param: TypeParamRef): List[TypeParamRef] = upperLens(this, param.binder, param.paramNum) - def minLower(param: PolyParam): List[PolyParam] = { + def minLower(param: TypeParamRef): List[TypeParamRef] = { val all = lower(param) all.filterNot(p => all.exists(isLess(p, _))) } - def minUpper(param: PolyParam): List[PolyParam] = { + def minUpper(param: TypeParamRef): List[TypeParamRef] = { val all = upper(param) all.filterNot(p => all.exists(isLess(_, p))) } - def exclusiveLower(param: PolyParam, butNot: PolyParam): List[PolyParam] = + def exclusiveLower(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef] = lower(param).filterNot(isLess(_, butNot)) - def exclusiveUpper(param: PolyParam, butNot: PolyParam): List[PolyParam] = + def exclusiveUpper(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef] = upper(param).filterNot(isLess(butNot, _)) -// ---------- Info related to PolyParams ------------------------------------------- +// ---------- Info related to TypeParamRefs ------------------------------------------- - def isLess(param1: PolyParam, param2: PolyParam): Boolean = + def isLess(param1: TypeParamRef, param2: TypeParamRef): Boolean = upper(param1).contains(param2) - def nonParamBounds(param: PolyParam): TypeBounds = + def nonParamBounds(param: TypeParamRef): TypeBounds = entry(param).asInstanceOf[TypeBounds] - def fullLowerBound(param: PolyParam)(implicit ctx: Context): Type = + def fullLowerBound(param: TypeParamRef)(implicit ctx: Context): Type = (nonParamBounds(param).lo /: minLower(param))(_ | _) - def fullUpperBound(param: PolyParam)(implicit ctx: Context): Type = + def fullUpperBound(param: TypeParamRef)(implicit ctx: Context): Type = (nonParamBounds(param).hi /: minUpper(param))(_ & _) - def fullBounds(param: PolyParam)(implicit ctx: Context): TypeBounds = + def fullBounds(param: TypeParamRef)(implicit ctx: Context): TypeBounds = nonParamBounds(param).derivedTypeBounds(fullLowerBound(param), fullUpperBound(param)) - def typeVarOfParam(param: PolyParam): Type = { + def typeVarOfParam(param: TypeParamRef): Type = { val entries = boundsMap(param.binder) if (entries == null) NoType else { @@ -219,8 +219,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * Q <: tp implies Q <: P and isUpper = true, or * tp <: Q implies P <: Q and isUpper = false */ - def dependentParams(tp: Type, isUpper: Boolean): List[PolyParam] = tp match { - case param: PolyParam if contains(param) => + def dependentParams(tp: Type, isUpper: Boolean): List[TypeParamRef] = tp match { + case param: TypeParamRef if contains(param) => param :: (if (isUpper) upper(param) else lower(param)) case tp: AndOrType => val ps1 = dependentParams(tp.tp1, isUpper) @@ -255,9 +255,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * * @param isUpper If true, `bound` is an upper bound, else a lower bound. */ - private def stripParams(tp: Type, paramBuf: mutable.ListBuffer[PolyParam], + private def stripParams(tp: Type, paramBuf: mutable.ListBuffer[TypeParamRef], isUpper: Boolean)(implicit ctx: Context): Type = tp match { - case param: PolyParam if contains(param) => + case param: TypeParamRef if contains(param) => if (!paramBuf.contains(param)) paramBuf += param NoType case tp: AndOrType if isUpper == tp.isAnd => @@ -275,7 +275,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * A top or bottom type if type consists only of dependent parameters. * @param isUpper If true, `bound` is an upper bound, else a lower bound. */ - private def normalizedType(tp: Type, paramBuf: mutable.ListBuffer[PolyParam], + private def normalizedType(tp: Type, paramBuf: mutable.ListBuffer[TypeParamRef], isUpper: Boolean)(implicit ctx: Context): Type = stripParams(tp, paramBuf, isUpper) .orElse(if (isUpper) defn.AnyType else defn.NothingType) @@ -295,10 +295,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds, */ private def init(poly: PolyType)(implicit ctx: Context): This = { var current = this - val loBuf, hiBuf = new mutable.ListBuffer[PolyParam] + val loBuf, hiBuf = new mutable.ListBuffer[TypeParamRef] var i = 0 while (i < poly.paramNames.length) { - val param = PolyParam(poly, i) + val param = TypeParamRef(poly, i) val bounds = nonParamBounds(param) val lo = normalizedType(bounds.lo, loBuf, isUpper = false) val hi = normalizedType(bounds.hi, hiBuf, isUpper = true) @@ -318,7 +318,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, /** Add the fact `param1 <: param2` to the constraint `current` and propagate * `<:<` relationships between parameters ("edges") but not bounds. */ - private def order(current: This, param1: PolyParam, param2: PolyParam)(implicit ctx: Context): This = + private def order(current: This, param1: TypeParamRef, param2: TypeParamRef)(implicit ctx: Context): This = if (param1 == param2 || current.isLess(param1, param2)) this else { assert(contains(param1)) @@ -330,10 +330,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds, current2 } - def addLess(param1: PolyParam, param2: PolyParam)(implicit ctx: Context): This = + def addLess(param1: TypeParamRef, param2: TypeParamRef)(implicit ctx: Context): This = order(this, param1, param2) - def updateEntry(current: This, param: PolyParam, tp: Type)(implicit ctx: Context): This = { + def updateEntry(current: This, param: TypeParamRef, tp: Type)(implicit ctx: Context): This = { var current1 = boundsLens.update(this, current, param, tp) tp match { case TypeBounds(lo, hi) => @@ -346,10 +346,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds, current1 } - def updateEntry(param: PolyParam, tp: Type)(implicit ctx: Context): This = + def updateEntry(param: TypeParamRef, tp: Type)(implicit ctx: Context): This = updateEntry(this, param, tp) - def unify(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This = { + def unify(p1: TypeParamRef, p2: TypeParamRef)(implicit ctx: Context): This = { val p1Bounds = (nonParamBounds(p1) & nonParamBounds(p2)).substParam(p2, p1) updateEntry(p1, p1Bounds).replace(p2, p1) } @@ -381,7 +381,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * would not find out where we need to approximate. Occurrences of parameters * that are not top-level are not affected. */ - def replace(param: PolyParam, tp: Type)(implicit ctx: Context): OrderingConstraint = { + def replace(param: TypeParamRef, tp: Type)(implicit ctx: Context): OrderingConstraint = { val replacement = tp.dealias.stripTypeVar if (param == replacement) this else { @@ -389,7 +389,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, val poly = param.binder val idx = param.paramNum - def removeParam(ps: List[PolyParam]) = + def removeParam(ps: List[TypeParamRef]) = ps.filterNot(p => p.binder.eq(poly) && p.paramNum == idx) def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int): Type = tp match { @@ -404,7 +404,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } def normalize(tp: Type, isUpper: Boolean): Type = tp match { - case p: PolyParam if p.binder == atPoly && p.paramNum == atIdx => + case p: TypeParamRef if p.binder == atPoly && p.paramNum == atIdx => if (isUpper) defn.AnyType else defn.NothingType case tp: AndOrType if isUpper == tp.isAnd => recombine(tp, normalize, isUpper) case _ => tp @@ -434,7 +434,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def remove(pt: PolyType)(implicit ctx: Context): This = { def removeFromOrdering(po: ParamOrdering) = { - def removeFromBoundss(key: PolyType, bndss: Array[List[PolyParam]]): Array[List[PolyParam]] = { + def removeFromBoundss(key: PolyType, bndss: Array[List[TypeParamRef]]): Array[List[TypeParamRef]] = { val bndss1 = bndss.map(_.filterConserve(_.binder ne pt)) if (bndss.corresponds(bndss1)(_ eq _)) bndss else bndss1 } @@ -458,17 +458,17 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def domainPolys: List[PolyType] = boundsMap.keys - def domainParams: List[PolyParam] = + def domainParams: List[TypeParamRef] = for { (poly, entries) <- boundsMap.toList n <- 0 until paramCount(entries) if entries(n).exists - } yield PolyParam(poly, n) + } yield TypeParamRef(poly, n) - def forallParams(p: PolyParam => Boolean): Boolean = { + def forallParams(p: TypeParamRef => Boolean): Boolean = { boundsMap.foreachBinding { (poly, entries) => for (i <- 0 until paramCount(entries)) - if (isBounds(entries(i)) && !p(PolyParam(poly, i))) return false + if (isBounds(entries(i)) && !p(TypeParamRef(poly, i))) return false } true } @@ -503,7 +503,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, merged } - def mergeParams(ps1: List[PolyParam], ps2: List[PolyParam]) = + def mergeParams(ps1: List[TypeParamRef], ps2: List[TypeParamRef]) = (ps1 /: ps2)((ps1, p2) => if (ps1.contains(p2)) ps1 else p2 :: ps1) def mergeEntries(e1: Type, e2: Type): Type = e1 match { @@ -532,13 +532,13 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } override def checkClosed()(implicit ctx: Context): Unit = { - def isFreePolyParam(tp: Type) = tp match { - case PolyParam(binder: PolyType, _) => !contains(binder) + def isFreeTypeParamRef(tp: Type) = tp match { + case TypeParamRef(binder: PolyType, _) => !contains(binder) case _ => false } def checkClosedType(tp: Type, where: String) = if (tp != null) - assert(!tp.existsPart(isFreePolyParam), i"unclosed constraint: $this refers to $tp in $where") + assert(!tp.existsPart(isFreeTypeParamRef), i"unclosed constraint: $this refers to $tp in $where") boundsMap.foreachBinding((_, tps) => tps.foreach(checkClosedType(_, "bounds"))) lowerMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "lower")))) upperMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "upper")))) @@ -567,7 +567,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def checkNonCyclic()(implicit ctx: Context): Unit = domainParams.foreach(checkNonCyclic) - private def checkNonCyclic(param: PolyParam)(implicit ctx: Context): Unit = + private def checkNonCyclic(param: TypeParamRef)(implicit ctx: Context): Unit = assert(!isLess(param, param), i"cyclic constraint involving $param in $this") // ---------- toText ----------------------------------------------------- diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 931f0dc74..77767a38c 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -163,15 +163,15 @@ object TypeApplications { class Reducer(tycon: PolyType, args: List[Type])(implicit ctx: Context) extends TypeMap { private var available = (0 until args.length).toSet var allReplaced = true - def hasWildcardArg(p: PolyParam) = + def hasWildcardArg(p: TypeParamRef) = p.binder == tycon && args(p.paramNum).isInstanceOf[TypeBounds] - def canReduceWildcard(p: PolyParam) = + def canReduceWildcard(p: TypeParamRef) = !ctx.mode.is(Mode.AllowLambdaWildcardApply) || available.contains(p.paramNum) def apply(t: Type) = t match { - case t @ TypeAlias(p: PolyParam) if hasWildcardArg(p) && canReduceWildcard(p) => + case t @ TypeAlias(p: TypeParamRef) if hasWildcardArg(p) && canReduceWildcard(p) => available -= p.paramNum args(p.paramNum) - case p: PolyParam if p.binder == tycon => + case p: TypeParamRef if p.binder == tycon => args(p.paramNum) match { case TypeBounds(lo, hi) => if (ctx.mode.is(Mode.AllowLambdaWildcardApply)) { allReplaced = false; p } diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 9f4db5edd..a4ea1d28f 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -280,7 +280,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case _ => } thirdTry(tp1, tp2) - case tp1: PolyParam => + case tp1: TypeParamRef => def flagNothingBound = { if (!frozenConstraint && tp2.isRef(defn.NothingClass) && state.isGlobalCommittable) { def msg = s"!!! instantiated to Nothing: $tp1, constraint = ${constraint.show}" @@ -289,13 +289,13 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } true } - def comparePolyParam = + def compareTypeParamRef = ctx.mode.is(Mode.TypevarsMissContext) || isSubTypeWhenFrozen(bounds(tp1).hi, tp2) || { if (canConstrain(tp1)) addConstraint(tp1, tp2, fromBelow = false) && flagNothingBound else thirdTry(tp1, tp2) } - comparePolyParam + compareTypeParamRef case tp1: ThisType => val cls1 = tp1.cls tp2 match { @@ -373,8 +373,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { private def thirdTry(tp1: Type, tp2: Type): Boolean = tp2 match { case tp2: NamedType => thirdTryNamed(tp1, tp2) - case tp2: PolyParam => - def comparePolyParam = + case tp2: TypeParamRef => + def compareTypeParamRef = (ctx.mode is Mode.TypevarsMissContext) || { val alwaysTrue = // The following condition is carefully formulated to catch all cases @@ -391,7 +391,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { else fourthTry(tp1, tp2) } } - comparePolyParam + compareTypeParamRef case tp2: RefinedType => def compareRefinedSlow: Boolean = { val name2 = tp2.refinedName @@ -618,7 +618,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def isMatchingApply(tp1: Type): Boolean = tp1 match { case HKApply(tycon1, args1) => tycon1.dealias match { - case tycon1: PolyParam => + case tycon1: TypeParamRef => (tycon1 == tycon2 || canConstrain(tycon1) && tryInstantiate(tycon1, tycon2)) && isSubArgs(args1, args2, tparams) @@ -646,7 +646,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * and the resulting type application is a supertype of `tp1`, * or fallback to fourthTry. */ - def canInstantiate(tycon2: PolyParam): Boolean = { + def canInstantiate(tycon2: TypeParamRef): Boolean = { /** Let * @@ -672,7 +672,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { tycon1b = PolyType(tparams1.map(_.paramName))( tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds), tl => tycon1a.appliedTo(args1.take(lengthDiff) ++ - tparams1.indices.toList.map(PolyParam(tl, _)))) + tparams1.indices.toList.map(TypeParamRef(tl, _)))) (ctx.mode.is(Mode.TypevarsMissContext) || tryInstantiate(tycon2, tycon1b.ensureHK)) && isSubType(tp1, tycon1b.appliedTo(args2)) @@ -725,7 +725,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { fallback(tycon2bounds.lo) tycon2 match { - case param2: PolyParam => + case param2: TypeParamRef => isMatchingApply(tp1) || { if (canConstrain(param2)) canInstantiate(param2) else compareLower(bounds(param2), tyconIsTypeRef = false) @@ -746,7 +746,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { */ def compareHkApply1(tp1: HKApply, tycon1: Type, args1: List[Type], tp2: Type): Boolean = tycon1 match { - case param1: PolyParam => + case param1: TypeParamRef => def canInstantiate = tp2 match { case AppliedType(tycon2, args2) => tryInstantiate(param1, tycon2.ensureHK) && isSubArgs(args1, args2, tycon2.typeParams) @@ -806,7 +806,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def fix(tp: Type): Type = tp.stripTypeVar match { case tp: RecType => fix(tp.parent).substRecThis(tp, anchor) case tp @ RefinedType(parent, rname, rinfo) => tp.derivedRefinedType(fix(parent), rname, rinfo) - case tp: PolyParam => fixOrElse(bounds(tp).hi, tp) + case tp: TypeParamRef => fixOrElse(bounds(tp).hi, tp) case tp: TypeProxy => fixOrElse(tp.underlying, tp) case tp: AndOrType => tp.derivedAndOrType(fix(tp.tp1), fix(tp.tp2)) case tp => tp @@ -967,7 +967,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Defer constraining type variables when compared against prototypes */ def isMatchedByProto(proto: ProtoType, tp: Type) = tp.stripTypeVar match { - case tp: PolyParam if constraint contains tp => true + case tp: TypeParamRef if constraint contains tp => true case _ => proto.isMatchedBy(tp) } @@ -978,7 +978,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * type variable with (the corresponding type in) `tp2` instead. */ private def isCappable(tp: Type): Boolean = tp match { - case tp: PolyParam => constraint contains tp + case tp: TypeParamRef => constraint contains tp case tp: TypeProxy => isCappable(tp.underlying) case tp: AndOrType => isCappable(tp.tp1) || isCappable(tp.tp2) case _ => false @@ -1424,7 +1424,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def showGoal(tp1: Type, tp2: Type)(implicit ctx: Context) = { println(ex"assertion failure for $tp1 <:< $tp2, frozen = $frozenConstraint") def explainPoly(tp: Type) = tp match { - case tp: PolyParam => ctx.echo(s"polyparam ${tp.show} found in ${tp.binder.show}") + case tp: TypeParamRef => ctx.echo(s"TypeParamRef ${tp.show} found in ${tp.binder.show}") case tp: TypeRef if tp.symbol.exists => ctx.echo(s"typeref ${tp.show} found in ${tp.symbol.owner.show}") case tp: TypeVar => ctx.echo(s"typevar ${tp.show}, origin = ${tp.origin}") case _ => ctx.echo(s"${tp.show} is a ${tp.getClass}") @@ -1503,7 +1503,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) { super.glb(tp1, tp2) } - override def addConstraint(param: PolyParam, bound: Type, fromBelow: Boolean): Boolean = + override def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean): Boolean = traceIndented(i"add constraint $param ${if (fromBelow) ">:" else "<:"} $bound $frozenConstraint, constraint = ${ctx.typerState.constraint}") { super.addConstraint(param, bound, fromBelow) } diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index b716318c1..07d613c57 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -28,7 +28,7 @@ import scala.annotation.tailrec * WildcardType * ErrorType * - * only for isInstanceOf, asInstanceOf: PolyType, PolyParam, TypeBounds + * only for isInstanceOf, asInstanceOf: PolyType, TypeParamRef, TypeBounds * */ object TypeErasure { @@ -204,7 +204,7 @@ object TypeErasure { !tp.symbol.isClass && !tp.derivesFrom(defn.ObjectClass) && !tp.symbol.is(JavaDefined) - case tp: PolyParam => + case tp: TypeParamRef => !tp.derivesFrom(defn.ObjectClass) && !tp.binder.resultType.isInstanceOf[JavaMethodType] case tp: TypeAlias => isUnboundedGeneric(tp.alias) @@ -304,7 +304,7 @@ object TypeErasure { case _: ClassInfo => true case _ => false } - case tp: PolyParam => false + case tp: TypeParamRef => false case tp: TypeProxy => hasStableErasure(tp.superType) case tp: AndOrType => hasStableErasure(tp.tp1) && hasStableErasure(tp.tp2) case _ => false diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 3d2906320..9593bfe93 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -157,7 +157,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. tp2 case tp1 => tp1 } - case tp: PolyParam => + case tp: TypeParamRef => typerState.constraint.typeVarOfParam(tp) orElse tp case _: ThisType | _: BoundType | NoPrefix => tp diff --git a/compiler/src/dotty/tools/dotc/core/TyperState.scala b/compiler/src/dotty/tools/dotc/core/TyperState.scala index 206438d86..08bef86b7 100644 --- a/compiler/src/dotty/tools/dotc/core/TyperState.scala +++ b/compiler/src/dotty/tools/dotc/core/TyperState.scala @@ -42,7 +42,7 @@ class TyperState(r: Reporter) extends DotClass with Showable { */ def instType(tvar: TypeVar)(implicit ctx: Context): Type = constraint.entry(tvar.origin) match { case _: TypeBounds => NoType - case tp: PolyParam => + case tp: TypeParamRef => var tvar1 = constraint.typeVarOfParam(tp) if (tvar1.exists) tvar1 else tp case tp => tp diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5629668c1..59c84910b 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -57,7 +57,7 @@ object Types { * | | +--- TermParamRef * | | +----RecThis * | | +--- SkolemType - * | +- PolyParam + * | +- TypeParamRef * | +- RefinedOrRecType -+-- RefinedType * | | -+-- RecType * | +- HKApply @@ -446,7 +446,7 @@ object Types { if mt.paramInfos.isEmpty && (tp.symbol is Stable) => mt.resultType case tp1 => tp1 }) - case tp: PolyParam => + case tp: TypeParamRef => goParam(tp) case tp: RecType => goRec(tp) @@ -563,7 +563,7 @@ object Types { // loadClassWithPrivateInnerAndSubSelf in ShowClassTests go(tp.cls.typeRef) orElse d } - def goParam(tp: PolyParam) = { + def goParam(tp: TypeParamRef) = { val next = tp.underlying ctx.typerState.constraint.entry(tp) match { case bounds: TypeBounds if bounds ne next => @@ -1180,8 +1180,8 @@ object Types { final def substDealias(from: List[Symbol], to: List[Type])(implicit ctx: Context): Type = ctx.substDealias(this, from, to, null) - /** Substitute all types of the form `PolyParam(from, N)` by - * `PolyParam(to, N)`. + /** Substitute all types of the form `TypeParamRef(from, N)` by + * `TypeParamRef(to, N)`. */ final def subst(from: BindingType, to: BindingType)(implicit ctx: Context): Type = ctx.subst(this, from, to, null) @@ -2673,7 +2673,7 @@ object Types { def isDependent(implicit ctx: Context) = true def isParamDependent(implicit ctx: Context) = true - def newParamRef(n: Int) = PolyParam(this, n) + def newParamRef(n: Int) = TypeParamRef(this, n) /** Instantiate parameter bounds by substituting parameters with given arguments */ final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] = @@ -2709,7 +2709,7 @@ object Types { case that: PolyType => val shift = new TypeMap { def apply(t: Type) = t match { - case PolyParam(`that`, n) => PolyParam(that, n + paramNames.length) + case TypeParamRef(`that`, n) => TypeParamRef(that, n + paramNames.length) case t => mapOver(t) } } @@ -2742,11 +2742,6 @@ object Types { override def computeHash = doHash(paramNames, resType, paramInfos) } - object PolyParam { - def apply(pt: PolyType, n: Int) = new TypeParamRef(pt, n) - def unapply(poly: PolyParam) = Some(poly.binder, poly.paramNum) - } - object PolyType { def apply(paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], @@ -2772,8 +2767,8 @@ object Types { def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type = paramInfo def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance - def toArg: Type = PolyParam(tl, n) - def paramRef(implicit ctx: Context): Type = PolyParam(tl, n) + def toArg: Type = TypeParamRef(tl, n) + def paramRef(implicit ctx: Context): Type = TypeParamRef(tl, n) } /** A higher kinded type application `C[T_1, ..., T_n]` */ @@ -2826,7 +2821,7 @@ object Types { protected def checkInst(implicit ctx: Context): this.type = { def check(tycon: Type): Unit = tycon.stripTypeVar match { case tycon: TypeRef if !tycon.symbol.isClass => - case _: PolyParam | _: ErrorType | _: WildcardType => + case _: TypeParamRef | _: ErrorType | _: WildcardType => case _: PolyType => assert(args.exists(_.isInstanceOf[TypeBounds]), s"unreduced type apply: $this") case tycon: AnnotatedType => @@ -2846,7 +2841,7 @@ object Types { unique(new CachedHKApply(tycon, args)).checkInst } - // ----- Bound types: MethodParam, PolyParam -------------------------- + // ----- Bound types: MethodParam, TypeParamRef -------------------------- abstract class BoundType extends CachedProxyType with ValueType { type BT <: Type @@ -2907,8 +2902,6 @@ object Types { } } - type PolyParam = TypeParamRef - /** a self-reference to an enclosing recursive type. */ case class RecThis(binder: RecType) extends BoundType with SingletonType { type BT = RecType @@ -2977,7 +2970,7 @@ object Types { * `owningTree` and `owner` are used to determine whether a type-variable can be instantiated * at some given point. See `Inferencing#interpolateUndetVars`. */ - final class TypeVar(val origin: PolyParam, creatorState: TyperState, val bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType { + final class TypeVar(val origin: TypeParamRef, creatorState: TyperState, val bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType { /** The permanent instance type of the variable, or NoType is none is given yet */ private[core] var inst: Type = NoType @@ -3854,7 +3847,7 @@ object Types { apply(x, tp.underlying) case tp: TermParamRef => apply(x, tp.underlying) - case tp: PolyParam => + case tp: TypeParamRef => apply(x, tp.underlying) case _ => foldOver(x, tp) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index a9cd9be1d..0b361f1f4 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -259,7 +259,7 @@ class TreePickler(pickler: TastyPickler) { case tpe: MethodType if richTypes => writeByte(METHODtype) pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) - case tpe: PolyParam => + case tpe: TypeParamRef => if (!pickleParamType(tpe)) // TODO figure out why this case arises in e.g. pickling AbstractFileReader. ctx.typerState.constraint.entry(tpe) match { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 067fd6076..c4ff3898c 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -283,7 +283,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle result case PARAMtype => readTypeRef() match { - case binder: PolyType => PolyParam(binder, readNat()) + case binder: PolyType => TypeParamRef(binder, readNat()) case binder: MethodType => binder.newParamRef(readNat()) } case CLASSconst => diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index 760b22689..e8fa45403 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -107,7 +107,7 @@ object Formatting { else nonSensicalStartTag + str + nonSensicalEndTag } - private type Recorded = AnyRef /*Symbol | PolyParam*/ + private type Recorded = AnyRef /*Symbol | TypeParamRef*/ private class Seen extends mutable.HashMap[String, List[Recorded]] { @@ -135,8 +135,8 @@ object Formatting { if ((sym is ModuleClass) && sym.sourceModule.exists) simpleNameString(sym.sourceModule) else seen.record(super.simpleNameString(sym), sym) - override def polyParamNameString(param: PolyParam): String = - seen.record(super.polyParamNameString(param), param) + override def TypeParamRefNameString(param: TypeParamRef): String = + seen.record(super.TypeParamRefNameString(param), param) } /** Create explanation for single `Recorded` type or symbol */ @@ -161,7 +161,7 @@ object Formatting { } entry match { - case param: PolyParam => + case param: TypeParamRef => s"is a type variable${addendum("constraint", ctx.typeComparer.bounds(param))}" case sym: Symbol => s"is a ${ctx.printer.kindString(sym)}${sym.showExtendedLocation}${addendum("bounds", sym.info)}" @@ -175,7 +175,7 @@ object Formatting { */ private def explanations(seen: Seen)(implicit ctx: Context): String = { def needsExplanation(entry: Recorded) = entry match { - case param: PolyParam => ctx.typerState.constraint.contains(param) + case param: TypeParamRef => ctx.typerState.constraint.contains(param) case _ => false } diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index a4f9921db..94621056f 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -182,8 +182,8 @@ class PlainPrinter(_ctx: Context) extends Printer { "]" ~ (" => " provided !tp.resultType.isInstanceOf[MethodType]) ~ toTextGlobal(tp.resultType) } - case tp: PolyParam => - polyParamNameString(tp) ~ lambdaHash(tp.binder) + case tp: TypeParamRef => + TypeParamRefNameString(tp) ~ lambdaHash(tp.binder) case AnnotatedType(tpe, annot) => toTextLocal(tpe) ~ " " ~ toText(annot) case HKApply(tycon, args) => @@ -206,10 +206,10 @@ class PlainPrinter(_ctx: Context) extends Printer { } }.close - protected def polyParamNameString(name: TypeName): String = name.toString + protected def TypeParamRefNameString(name: TypeName): String = name.toString - protected def polyParamNameString(param: PolyParam): String = - polyParamNameString(param.binder.paramNames(param.paramNum)) + protected def TypeParamRefNameString(param: TypeParamRef): String = + TypeParamRefNameString(param.binder.paramNames(param.paramNum)) /** The name of the symbol without a unique id. Under refined printing, * the decoded original name. diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 8a33472b8..488e66d8d 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -604,7 +604,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { def optText[T >: Untyped](tree: List[Tree[T]])(encl: Text => Text): Text = if (tree.exists(!_.isEmpty)) encl(blockText(tree)) else "" - override protected def polyParamNameString(name: TypeName): String = + override protected def TypeParamRefNameString(name: TypeName): String = name.unexpandedName.toString override protected def treatAsTypeParam(sym: Symbol): Boolean = sym is TypeParam diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index d608dc7c4..28ce9aa5a 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -258,7 +258,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverse(tp.underlying) case tp: TermParamRef => traverse(tp.underlying) - case tp: PolyParam => + case tp: TypeParamRef => traverse(tp.underlying) case _ => traverseChildren(tp) diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index dd318861a..0b9ec9085 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -113,7 +113,7 @@ trait FullParameterization { /** Replace class type parameters by the added type parameters of the polytype `pt` */ def mapClassParams(tp: Type, pt: PolyType): Type = { val classParamsRange = (mtparamCount until mtparamCount + ctparams.length).toList - tp.substDealias(ctparams, classParamsRange map (PolyParam(pt, _))) + tp.substDealias(ctparams, classParamsRange map (TypeParamRef(pt, _))) } /** The bounds for the added type parameters of the polytype `pt` */ diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index dd4d95257..dde037938 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -287,7 +287,7 @@ class TreeChecker extends Phase with SymTransformer { res } - /** Check that PolyParams and MethodParams refer to an enclosing type */ + /** Check that TypeParamRefs and MethodParams refer to an enclosing type */ def checkNoOrphans(tp: Type)(implicit ctx: Context) = new TypeMap() { val definedBinders = mutable.Set[Type]() def apply(tp: Type): Type = { diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index d1a73fd65..ceaf3471a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -195,7 +195,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => } /** The function's type after widening and instantiating polytypes - * with polyparams in constraint set + * with TypeParamRefs in constraint set */ val methType = funType.widen match { case funType: MethodType => funType diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index ff998e233..5f9eae3da 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -121,12 +121,12 @@ object ErrorReporting { } def typeMismatchMsg(found: Type, expected: Type, postScript: String = "") = { - // replace constrained polyparams and their typevars by their bounds where possible + // replace constrained TypeParamRefs and their typevars by their bounds where possible object reported extends TypeMap { def setVariance(v: Int) = variance = v val constraint = ctx.typerState.constraint def apply(tp: Type): Type = tp match { - case tp: PolyParam => + case tp: TypeParamRef => constraint.entry(tp) match { case bounds: TypeBounds => if (variance < 0) apply(constraint.fullUpperBound(tp)) diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index 20efd4083..18a1982e1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -176,7 +176,7 @@ object Inferencing { * -1 (minimize) if constraint is uniformly from below, * 0 if unconstrained, or constraint is from below and above. */ - private def instDirection(param: PolyParam)(implicit ctx: Context): Int = { + private def instDirection(param: TypeParamRef)(implicit ctx: Context): Int = { val constrained = ctx.typerState.constraint.fullBounds(param) val original = param.binder.paramInfos(param.paramNum) val cmp = ctx.typeComparer diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 8520dcdfc..cf3076fce 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -358,7 +358,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { * 2. If given type refers to a parameter, make `paramProxy` refer to the entry stored * in `paramNames` under the parameter's name. This roundabout way to bind parameter * references to proxies is done because we not known a priori what the parameter - * references of a method are (we only know the method's type, but that contains PolyParams + * references of a method are (we only know the method's type, but that contains TypeParamRefs * and MethodParams, not TypeRefs or TermRefs. */ private def registerType(tpe: Type): Unit = tpe match { diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 89e4f93e2..2dccbbcc1 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -192,7 +192,7 @@ object ProtoTypes { /** Forget the types of any arguments that have been typed producing a constraint in a * typer state that is not yet committed into the one of the current context `ctx`. - * This is necessary to avoid "orphan" PolyParams that are referred to from + * This is necessary to avoid "orphan" TypeParamRefs that are referred to from * type variables in the typed arguments, but that are not registered in the * current constraint. A test case is pos/t1756.scala. * @return True if all arguments have types (in particular, no types were forgotten). @@ -385,7 +385,7 @@ object ProtoTypes { for (n <- (0 until pt.paramNames.length).toList) yield { val tt = new TypeTree().withPos(owningTree.pos) - tt.withType(new TypeVar(PolyParam(pt, n), state, tt, ctx.owner)) + tt.withType(new TypeVar(TypeParamRef(pt, n), state, tt, ctx.owner)) } val added = @@ -399,22 +399,22 @@ object ProtoTypes { /** Same as `constrained(pt, EmptyTree)`, but returns just the created polytype */ def constrained(pt: PolyType)(implicit ctx: Context): PolyType = constrained(pt, EmptyTree)._1 - /** Create a new polyparam that represents a dependent method parameter singleton */ - def newDepPolyParam(tp: Type)(implicit ctx: Context): PolyParam = { + /** Create a new TypeParamRef that represents a dependent method parameter singleton */ + def newDepTypeParamRef(tp: Type)(implicit ctx: Context): TypeParamRef = { val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil)( pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil, pt => defn.AnyType) ctx.typeComparer.addToConstraint(poly, Nil) - PolyParam(poly, 0) + TypeParamRef(poly, 0) } /** The result type of `mt`, where all references to parameters of `mt` are - * replaced by either wildcards (if typevarsMissContext) or polyparams. + * replaced by either wildcards (if typevarsMissContext) or TypeParamRefs. */ def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type = if (mt.isDependent) { def replacement(tp: Type) = - if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepPolyParam(tp) + if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepTypeParamRef(tp) mt.resultType.substParams(mt, mt.paramInfos.map(replacement)) } else mt.resultType @@ -458,7 +458,7 @@ object ProtoTypes { /** Approximate occurrences of parameter types and uninstantiated typevars * by wildcard types. */ - final def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[PolyParam])(implicit ctx: Context): Type = tp match { + final def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[TypeParamRef])(implicit ctx: Context): Type = tp match { case tp: NamedType => // default case, inlined for speed if (tp.symbol.isStatic) tp else tp.derivedSelect(wildApprox(tp.prefix, theMap, seen)) @@ -469,7 +469,7 @@ object ProtoTypes { wildApprox(tp.refinedInfo, theMap, seen)) case tp: TypeAlias => // default case, inlined for speed tp.derivedTypeAlias(wildApprox(tp.alias, theMap, seen)) - case tp @ PolyParam(poly, pnum) => + case tp @ TypeParamRef(poly, pnum) => def wildApproxBounds(bounds: TypeBounds) = if (bounds.lo.isInstanceOf[NamedType] && bounds.hi.isInstanceOf[NamedType]) WildcardType(wildApprox(bounds, theMap, seen).bounds) @@ -532,7 +532,7 @@ object ProtoTypes { @sharable object AssignProto extends UncachedGroundType with MatchAlways - private[ProtoTypes] class WildApproxMap(val seen: Set[PolyParam])(implicit ctx: Context) extends TypeMap { + private[ProtoTypes] class WildApproxMap(val seen: Set[TypeParamRef])(implicit ctx: Context) extends TypeMap { def apply(tp: Type) = wildApprox(tp, this, seen) } diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 717429848..ed71f2239 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -348,7 +348,7 @@ trait TypeAssigner { val newIndex = gapBuf.length gapBuf += idx // Re-index unassigned type arguments that remain after transformation - PolyParam(pt, newIndex) + TypeParamRef(pt, newIndex) } // Type parameters after naming assignment, conserving paramNames order @@ -358,7 +358,7 @@ trait TypeAssigner { val transform = new TypeMap { def apply(t: Type) = t match { - case PolyParam(`pt`, idx) => normArgs(idx) + case TypeParamRef(`pt`, idx) => normArgs(idx) case _ => mapOver(t) } } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 5e845a807..145410f65 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1871,7 +1871,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case TypeBounds(lo, hi) if (lo eq hi) || (hi <:< lo)(ctx.fresh.setExploreTyperState) => inst(lo) - case tp: PolyParam => + case tp: TypeParamRef => constraint.typeVarOfParam(tp).orElse(tp) case _ => tp } -- cgit v1.2.3 From 78e6cc748b4dcde30bdac3618c4804ff65f32e45 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 14:02:29 +0100 Subject: Make PolyTypes subtypes of LambdaTypes Also, rename LambdaOver{Type,Term}s to {Type,Term}Lambda --- .../src/dotty/tools/dotc/core/Constraint.scala | 18 ++-- .../dotty/tools/dotc/core/OrderingConstraint.scala | 54 +++++----- .../src/dotty/tools/dotc/core/TyperState.scala | 6 +- compiler/src/dotty/tools/dotc/core/Types.scala | 109 ++++++++++----------- 4 files changed, 89 insertions(+), 98 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala index fe14aa53c..7a0e6dece 100644 --- a/compiler/src/dotty/tools/dotc/core/Constraint.scala +++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala @@ -13,17 +13,17 @@ 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 - * - TypeParamRef The parameters of the constrained polytypes - * - TypeVar Every constrained parameter might be associated with a TypeVar - * that has the TypeParamRef as origin. + * - TypeLambda A constraint constrains the type parameters of a set of TypeLambdas + * - TypeParamRef The parameters of the constrained polytypes + * - 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: TypeParamRef): Boolean @@ -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`. @@ -115,13 +115,13 @@ abstract class Constraint extends Showable { * 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] + def domainPolys: List[TypeLambda] /** The polytype parameters constrained by this constraint */ def domainParams: List[TypeParamRef] diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index dbb952369..2dff39c37 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -14,7 +14,7 @@ import annotation.tailrec object OrderingConstraint { - type ArrayValuedMap[T] = SimpleMap[PolyType, Array[T]] + type ArrayValuedMap[T] = SimpleMap[TypeLambda, Array[T]] /** The type of `OrderingConstraint#boundsMap` */ type ParamBounds = ArrayValuedMap[Type] @@ -32,11 +32,11 @@ object OrderingConstraint { /** A lens for updating a single entry array in one of the three constraint maps */ abstract class ConstraintLens[T <: AnyRef: ClassTag] { - def entries(c: OrderingConstraint, poly: PolyType): Array[T] - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[T])(implicit ctx: Context): OrderingConstraint + def entries(c: OrderingConstraint, poly: TypeLambda): Array[T] + def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[T])(implicit ctx: Context): OrderingConstraint def initial: T - def apply(c: OrderingConstraint, poly: PolyType, idx: Int) = { + def apply(c: OrderingConstraint, poly: TypeLambda, idx: Int) = { val es = entries(c, poly) if (es == null) initial else es(idx) } @@ -47,7 +47,7 @@ object OrderingConstraint { * parts of `current` which are not shared by `prev`. */ def update(prev: OrderingConstraint, current: OrderingConstraint, - poly: PolyType, idx: Int, entry: T)(implicit ctx: Context): OrderingConstraint = { + poly: TypeLambda, idx: Int, entry: T)(implicit ctx: Context): OrderingConstraint = { var es = entries(current, poly) if (es != null && (es(idx) eq entry)) current else { @@ -72,7 +72,7 @@ object OrderingConstraint { update(prev, current, param.binder, param.paramNum, entry) def map(prev: OrderingConstraint, current: OrderingConstraint, - poly: PolyType, idx: Int, f: T => T)(implicit ctx: Context): OrderingConstraint = + poly: TypeLambda, idx: Int, f: T => T)(implicit ctx: Context): OrderingConstraint = update(prev, current, poly, idx, f(apply(current, poly, idx))) def map(prev: OrderingConstraint, current: OrderingConstraint, @@ -81,25 +81,25 @@ object OrderingConstraint { } val boundsLens = new ConstraintLens[Type] { - def entries(c: OrderingConstraint, poly: PolyType): Array[Type] = + def entries(c: OrderingConstraint, poly: TypeLambda): Array[Type] = c.boundsMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[Type])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[Type])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap.updated(poly, entries), c.lowerMap, c.upperMap) def initial = NoType } val lowerLens = new ConstraintLens[List[TypeParamRef]] { - def entries(c: OrderingConstraint, poly: PolyType): Array[List[TypeParamRef]] = + def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] = c.lowerMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap.updated(poly, entries), c.upperMap) def initial = Nil } val upperLens = new ConstraintLens[List[TypeParamRef]] { - def entries(c: OrderingConstraint, poly: PolyType): Array[List[TypeParamRef]] = + def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] = c.upperMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap, c.upperMap.updated(poly, entries)) def initial = Nil } @@ -109,19 +109,19 @@ import OrderingConstraint._ /** Constraint over undetermined type parameters that keeps separate maps to * reflect parameter orderings. - * @param boundsMap a map from PolyType to arrays. + * @param boundsMap a map from TypeLambda to arrays. * Each array contains twice the number of entries as there a type parameters - * in the PolyType. The first half of the array contains the type bounds that constrain the + * in the TypeLambda. The first half of the array contains the type bounds that constrain the * polytype's type parameters. The second half might contain type variables that * track the corresponding parameters, or is left empty (filled with nulls). * An instantiated type parameter is represented by having its instance type in * the corresponding array entry. The dual use of arrays for poly params * and typevars is to save space and hopefully gain some speed. * - * @param lowerMap a map from PolyTypes to arrays. Each array entry corresponds + * @param lowerMap a map from TypeLambdas to arrays. Each array entry corresponds * to a parameter P of the polytype; it contains all constrained parameters * Q that are known to be smaller than P, i.e. Q <: P. - * @param upperMap a map from PolyTypes to arrays. Each array entry corresponds + * @param upperMap a map from TypeLambdas to arrays. Each array entry corresponds * to a parameter P of the polytype; it contains all constrained parameters * Q that are known to be greater than P, i.e. P <: Q. */ @@ -149,7 +149,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ----------- Contains tests -------------------------------------------------- - def contains(pt: PolyType): Boolean = boundsMap(pt) != null + def contains(pt: TypeLambda): Boolean = boundsMap(pt) != null def contains(param: TypeParamRef): Boolean = { val entries = boundsMap(param.binder) @@ -212,7 +212,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } } -// ---------- Adding PolyTypes -------------------------------------------------- +// ---------- Adding TypeLambdas -------------------------------------------------- /** The list of parameters P such that, for a fresh type parameter Q: * @@ -280,7 +280,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, stripParams(tp, paramBuf, isUpper) .orElse(if (isUpper) defn.AnyType else defn.NothingType) - def add(poly: PolyType, tvars: List[TypeVar])(implicit ctx: Context): This = { + def add(poly: TypeLambda, tvars: List[TypeVar])(implicit ctx: Context): This = { assert(!contains(poly)) val nparams = poly.paramNames.length val entries1 = new Array[Type](nparams * 2) @@ -293,7 +293,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * Update all bounds to be normalized and update ordering to account for * dependent parameters. */ - private def init(poly: PolyType)(implicit ctx: Context): This = { + private def init(poly: TypeLambda)(implicit ctx: Context): This = { var current = this val loBuf, hiBuf = new mutable.ListBuffer[TypeParamRef] var i = 0 @@ -392,7 +392,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def removeParam(ps: List[TypeParamRef]) = ps.filterNot(p => p.binder.eq(poly) && p.paramNum == idx) - def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int): Type = tp match { + def replaceParam(tp: Type, atPoly: TypeLambda, atIdx: Int): Type = tp match { case bounds @ TypeBounds(lo, hi) => def recombine(andor: AndOrType, op: (Type, Boolean) => Type, isUpper: Boolean): Type = { @@ -432,9 +432,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } } - def remove(pt: PolyType)(implicit ctx: Context): This = { + def remove(pt: TypeLambda)(implicit ctx: Context): This = { def removeFromOrdering(po: ParamOrdering) = { - def removeFromBoundss(key: PolyType, bndss: Array[List[TypeParamRef]]): Array[List[TypeParamRef]] = { + def removeFromBoundss(key: TypeLambda, bndss: Array[List[TypeParamRef]]): Array[List[TypeParamRef]] = { val bndss1 = bndss.map(_.filterConserve(_.binder ne pt)) if (bndss.corresponds(bndss1)(_ eq _)) bndss else bndss1 } @@ -443,7 +443,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, newConstraint(boundsMap.remove(pt), removeFromOrdering(lowerMap), removeFromOrdering(upperMap)) } - def isRemovable(pt: PolyType): Boolean = { + def isRemovable(pt: TypeLambda): Boolean = { val entries = boundsMap(pt) @tailrec def allRemovable(last: Int): Boolean = if (last < 0) true @@ -456,7 +456,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ---------- Exploration -------------------------------------------------------- - def domainPolys: List[PolyType] = boundsMap.keys + def domainPolys: List[TypeLambda] = boundsMap.keys def domainParams: List[TypeParamRef] = for { @@ -473,7 +473,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, true } - def foreachParam(p: (PolyType, Int) => Unit): Unit = + def foreachParam(p: (TypeLambda, Int) => Unit): Unit = boundsMap.foreachBinding { (poly, entries) => 0.until(poly.paramNames.length).foreach(p(poly, _)) } @@ -533,7 +533,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, override def checkClosed()(implicit ctx: Context): Unit = { def isFreeTypeParamRef(tp: Type) = tp match { - case TypeParamRef(binder: PolyType, _) => !contains(binder) + case TypeParamRef(binder: TypeLambda, _) => !contains(binder) case _ => false } def checkClosedType(tp: Type, where: String) = diff --git a/compiler/src/dotty/tools/dotc/core/TyperState.scala b/compiler/src/dotty/tools/dotc/core/TyperState.scala index 08bef86b7..b33b3aa29 100644 --- a/compiler/src/dotty/tools/dotc/core/TyperState.scala +++ b/compiler/src/dotty/tools/dotc/core/TyperState.scala @@ -155,14 +155,14 @@ extends TyperState(r) { } override def gc()(implicit ctx: Context): Unit = { - val toCollect = new mutable.ListBuffer[PolyType] + val toCollect = new mutable.ListBuffer[TypeLambda] constraint foreachTypeVar { tvar => if (!tvar.inst.exists) { val inst = instType(tvar) if (inst.exists && (tvar.owningState eq this)) { tvar.inst = inst - val poly = tvar.origin.binder - if (constraint.isRemovable(poly)) toCollect += poly + val lam = tvar.origin.binder + if (constraint.isRemovable(lam)) toCollect += lam } } } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 59c84910b..be861d863 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2319,10 +2319,10 @@ object Types { /** The lambda type square: * - * LambdaType | LambdaOverTerms | LambdaOverTypes + * LambdaType | TermLambda | TypeLambda * ------------+-------------------+------------------ * Proxy (hk) | HKTermLambda | HKTypeLambda - * Ground (*) | MethodType | PolyType + * Ground (*) | MethodType | PolyType */ trait LambdaType extends BindingType with MethodOrPoly { self => type ThisName <: Name @@ -2346,6 +2346,8 @@ object Types { lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef) + protected def computeSignature(implicit ctx: Context) = resultSignature + def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = if (isDependent) resultType.substParams(this, argTypes) else resultType @@ -2364,13 +2366,16 @@ object Types { case _ => false } + + protected def prefixString: String + override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" } - trait LambdaOverTerms extends LambdaType { thisLambdaType => - import LambdaOverTerms._ + trait TermLambda extends LambdaType { thisLambdaType => + import TermLambda._ type ThisName = TermName type PInfo = Type - type This = LambdaOverTerms + type This = TermLambda def paramNames: List[TermName] @@ -2465,7 +2470,7 @@ object Types { def newParamRef(n: Int) = TermParamRef(this, n) } - object LambdaOverTerms { + object TermLambda { private type DependencyStatus = Byte private final val Unknown: DependencyStatus = 0 // not yet computed private final val NoDeps: DependencyStatus = 1 // no dependent parameters found @@ -2475,12 +2480,10 @@ object Types { private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations } - type LambdaOverTypes = PolyType // (for now) - abstract case class MethodType(paramNames: List[TermName])( paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends CachedGroundType with TermType with LambdaOverTerms with NarrowCached { thisMethodType => + extends CachedGroundType with TermType with TermLambda with NarrowCached { thisMethodType => import MethodType._ protected def companion: MethodTypeCompanion @@ -2492,7 +2495,7 @@ object Types { val resType = resultTypeExp(this) assert(resType.exists) - protected def computeSignature(implicit ctx: Context): Signature = + override def computeSignature(implicit ctx: Context): Signature = resultSignature.prepend(paramInfos, isJava) def derivedMethodType(paramNames: List[TermName] = this.paramNames, @@ -2508,7 +2511,6 @@ object Types { override def computeHash = doHash(paramNames, resType, paramInfos) protected def prefixString = "MethodType" - override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" } final class CachedMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) @@ -2633,6 +2635,35 @@ object Types { } } + trait TypeLambda extends LambdaType { + type ThisName = TypeName + type PInfo = TypeBounds + type This = TypeLambda + + def isDependent(implicit ctx: Context): Boolean = true + + def newParamRef(n: Int) = TypeParamRef(this, n) + + lazy val typeParams: List[LambdaParam] = + paramNames.indices.toList.map(new LambdaParam(this, _)) + + /** Instantiate parameter bounds by substituting parameters with given arguments */ + final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] = + paramInfos.mapConserve(_.substParams(this, argTypes)) + + def derivedLambdaAbstraction(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): Type = + resType match { + case resType @ TypeAlias(alias) => + resType.derivedTypeAlias(newLikeThis(paramNames, paramInfos, alias)) + case resType @ TypeBounds(lo, hi) => + resType.derivedTypeBounds( + if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramInfos, lo), + newLikeThis(paramNames, paramInfos, hi)) + case _ => + derivedLambdaType(paramNames, paramInfos, resType) + } + } + /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T` * This is used both as a type of a polymorphic method and as a type of * a higher-kinded type parameter. Variances are encoded in parameter @@ -2648,11 +2679,7 @@ object Types { */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends CachedProxyType with LambdaType { - - type ThisName = TypeName - type PInfo = TypeBounds - type This = PolyType + extends CachedProxyType with TypeLambda { /** The bounds of the type parameters */ val paramInfos: List[TypeBounds] = paramInfosExp(this) @@ -2663,22 +2690,8 @@ object Types { assert(resType.isInstanceOf[TermType], this) assert(paramNames.nonEmpty) - protected def computeSignature(implicit ctx: Context) = resultSignature - - lazy val typeParams: List[LambdaParam] = - paramNames.indices.toList.map(new LambdaParam(this, _)) - - override def resultType(implicit ctx: Context) = resType override def underlying(implicit ctx: Context) = resType - def isDependent(implicit ctx: Context) = true - def isParamDependent(implicit ctx: Context) = true - def newParamRef(n: Int) = TypeParamRef(this, n) - - /** Instantiate parameter bounds by substituting parameters with given arguments */ - final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] = - paramInfos.mapConserve(_.substParams(this, argTypes)) - def newLikeThis(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType = PolyType.apply(paramNames)( x => paramInfos.mapConserve(_.subst(this, x).bounds), @@ -2687,20 +2700,7 @@ object Types { def derivedPolyType(paramNames: List[TypeName] = this.paramNames, paramInfos: List[TypeBounds] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = - if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this - else newLikeThis(paramNames, paramInfos, resType) - - def derivedLambdaAbstraction(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): Type = - resType match { - case resType @ TypeAlias(alias) => - resType.derivedTypeAlias(newLikeThis(paramNames, paramInfos, alias)) - case resType @ TypeBounds(lo, hi) => - resType.derivedTypeBounds( - if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramInfos, lo), - newLikeThis(paramNames, paramInfos, hi)) - case _ => - derivedPolyType(paramNames, paramInfos, resType) - } + derivedLambdaType(paramNames, paramInfos, resType) /** Merge nested polytypes into one polytype. nested polytypes are normally not supported * but can arise as temporary data structures. @@ -2729,16 +2729,7 @@ object Types { case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs) } - override def equals(other: Any) = other match { - case other: PolyType => - other.paramNames == this.paramNames && - other.paramInfos == this.paramInfos && - other.resType == this.resType - case _ => false - } - - override def toString = s"PolyType($paramNames, $paramInfos, $resType)" - + protected def prefixString = "PolyType" override def computeHash = doHash(paramNames, resType, paramInfos) } @@ -2760,7 +2751,7 @@ object Types { // ----- HK types: LambdaParam, HKApply --------------------- /** The parameter of a type lambda */ - case class LambdaParam(tl: PolyType, n: Int) extends ParamInfo { + case class LambdaParam(tl: TypeLambda, n: Int) extends ParamInfo { def isTypeParam(implicit ctx: Context) = tl.paramNames.head.isTypeName def paramName(implicit ctx: Context): TypeName = tl.paramNames(n) def paramInfo(implicit ctx: Context): Type = tl.paramInfos(n) @@ -2879,13 +2870,13 @@ object Types { } } - case class TermParamRef(binder: LambdaOverTerms, paramNum: Int) extends ParamRef { - type BT = LambdaOverTerms + case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef { + type BT = TermLambda def copyBoundType(bt: BT) = TermParamRef(bt, paramNum) } - case class TypeParamRef(binder: LambdaOverTypes, paramNum: Int) extends ParamRef { - type BT = LambdaOverTypes + case class TypeParamRef(binder: TypeLambda, paramNum: Int) extends ParamRef { + type BT = TypeLambda def copyBoundType(bt: BT) = TypeParamRef(bt, paramNum) /** Looking only at the structure of `bound`, is one of the following true? -- cgit v1.2.3 From ec4282dd99814ceb5304c4e1bb57aa607edff8db Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 14:39:48 +0100 Subject: Add StarLambda, HKLambda abstractions ... ... to distinguish between HK(proxy) and *(ground) types. Also, refactor some more methods to keep it DRY. --- compiler/src/dotty/tools/dotc/core/Types.scala | 149 +++++++++++++------------ 1 file changed, 79 insertions(+), 70 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index be861d863..49fc825ca 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2280,7 +2280,7 @@ object Types { if (tp1 eq tp2) tp1 else apply(tp1, tp2) } - // ----- Method types: MethodType/ExprType/PolyType ------------------------------- + // ----- ExprType and LambdaTypes ----------------------------------- // Note: method types are cached whereas poly types are not. The reason // is that most poly types are cyclic via poly params, @@ -2315,14 +2315,34 @@ object Types { } } + /** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */ + abstract case class ExprType(resType: Type) + extends CachedProxyType with TermType with MethodicType { + override def resultType(implicit ctx: Context): Type = resType + override def underlying(implicit ctx: Context): Type = resType + protected def computeSignature(implicit ctx: Context): Signature = resultSignature + def derivedExprType(resType: Type)(implicit ctx: Context) = + if (resType eq this.resType) this else ExprType(resType) + override def computeHash = doHash(resType) + } + + final class CachedExprType(resultType: Type) extends ExprType(resultType) + + object ExprType { + def apply(resultType: Type)(implicit ctx: Context) = { + assertUnerased() + unique(new CachedExprType(resultType)) + } + } + trait MethodOrPoly extends MethodicType /** The lambda type square: * * LambdaType | TermLambda | TypeLambda * ------------+-------------------+------------------ - * Proxy (hk) | HKTermLambda | HKTypeLambda - * Ground (*) | MethodType | PolyType + * HKLambda | HKTermLambda | HKTypeLambda + * StarLambda | MethodType | PolyType */ trait LambdaType extends BindingType with MethodOrPoly { self => type ThisName <: Name @@ -2332,8 +2352,6 @@ object Types { def paramNames: List[ThisName] def paramInfos: List[PInfo] def resType: Type - def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type) - (implicit ctx: Context): LambdaType { type ThisName = self.ThisName; type PInfo = self.PInfo } def newParamRef(n: Int): ParamRef override def resultType(implicit ctx: Context) = resType @@ -2348,34 +2366,50 @@ object Types { protected def computeSignature(implicit ctx: Context) = resultSignature - def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = + final def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = if (isDependent) resultType.substParams(this, argTypes) else resultType - def derivedLambdaType(paramNames: List[ThisName] = this.paramNames, + protected def companion: LambdaTypeCompanion[ThisName, PInfo, This] + + final def derivedLambdaType(paramNames: List[ThisName] = this.paramNames, paramInfos: List[PInfo] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this else newLikeThis(paramNames, paramInfos, resType) - override def equals(that: Any) = that match { + final def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): This = + companion(paramNames)( + x => paramInfos.mapConserve(_.subst(this, x).asInstanceOf[PInfo]), + x => resType.subst(this, x)) + + final override def equals(that: Any) = that match { case that: LambdaType => this.paramNames == that.paramNames && this.paramInfos == that.paramInfos && - this.resType == that.resType + this.resType == that.resType && + (this.companion eq that.companion) case _ => false } protected def prefixString: String - override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" + final override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" + } + + abstract class HKLambda extends CachedProxyType with LambdaType { + final override def computeHash = doHash(paramNames, resType, paramInfos) + } + + abstract class StarLambda extends CachedGroundType with LambdaType with TermType { + final override def computeHash = doHash(paramNames, resType, paramInfos) } trait TermLambda extends LambdaType { thisLambdaType => - import TermLambda._ + import DepStatus._ type ThisName = TermName type PInfo = Type - type This = TermLambda + type This <: TermLambda def paramNames: List[TermName] @@ -2396,8 +2430,8 @@ object Types { } else resType - var myDependencyStatus: DependencyStatus = Unknown - var myParamDependencyStatus: DependencyStatus = Unknown + private var myDependencyStatus: DependencyStatus = Unknown + private var myParamDependencyStatus: DependencyStatus = Unknown private def depStatus(initial: DependencyStatus, tp: Type)(implicit ctx: Context): DependencyStatus = { def combine(x: DependencyStatus, y: DependencyStatus) = { @@ -2470,22 +2504,14 @@ object Types { def newParamRef(n: Int) = TermParamRef(this, n) } - object TermLambda { - private type DependencyStatus = Byte - private final val Unknown: DependencyStatus = 0 // not yet computed - private final val NoDeps: DependencyStatus = 1 // no dependent parameters found - private final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types - private final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist - private final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status - private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations - } - abstract case class MethodType(paramNames: List[TermName])( paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends CachedGroundType with TermType with TermLambda with NarrowCached { thisMethodType => + extends StarLambda with TermLambda with NarrowCached { thisMethodType => import MethodType._ + type This = MethodType + protected def companion: MethodTypeCompanion def isJava = false @@ -2503,28 +2529,18 @@ object Types { resType: Type = this.resType)(implicit ctx: Context) = derivedLambdaType(paramNames, paramInfos, resType) - def newLikeThis(paramNames: List[TermName], paramInfos: List[Type], resType: Type)(implicit ctx: Context): MethodType = - companion(paramNames)( - x => paramInfos.mapConserve(_.subst(this, x)), - x => resType.subst(this, x)) - - override def computeHash = doHash(paramNames, resType, paramInfos) - protected def prefixString = "MethodType" } final class CachedMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { def companion = MethodType - override def equals(that: Any) = super.equals(that) && that.isInstanceOf[CachedMethodType] } final class JavaMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { def companion = JavaMethodType override def isJava = true - override def equals(that: Any) = super.equals(that) && that.isInstanceOf[JavaMethodType] - override def computeHash = addDelta(super.computeHash, 1) override protected def prefixString = "JavaMethodType" } @@ -2532,8 +2548,6 @@ object Types { extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { def companion = ImplicitMethodType override def isImplicit = true - override def equals(that: Any) = super.equals(that) && that.isInstanceOf[ImplicitMethodType] - override def computeHash = addDelta(super.computeHash, 2) override protected def prefixString = "ImplicitMethodType" } @@ -2548,8 +2562,17 @@ object Types { apply(syntheticParamNames(paramInfos.length), paramInfos, resultType) } - abstract class MethodTypeCompanion extends LambdaTypeCompanion[TermName, Type, MethodType] { - def syntheticParamNames(n: Int): List[TermName] = nme.syntheticParamNames(n) + abstract class TermLambdaCompanion[LT <: TermLambda] + extends LambdaTypeCompanion[TermName, Type, LT] { + def syntheticParamNames(n: Int) = nme.syntheticParamNames(n) + } + + abstract class TypeLambdaCompanion[LT <: TypeLambda] + extends LambdaTypeCompanion[TypeName, TypeBounds, LT] { + def syntheticParamNames(n: Int) = tpnme.syntheticTypeParamNames(n) + } + + abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters. @@ -2594,7 +2617,6 @@ object Types { } object MethodType extends MethodTypeCompanion { - def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = checkValid(unique(new CachedMethodType(paramNames)(paramInfosExp, resultTypeExp))) } @@ -2615,30 +2637,10 @@ object Types { Some((mt.paramNames, mt.paramInfos, mt.resultType)) } - /** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */ - abstract case class ExprType(resType: Type) - extends CachedProxyType with TermType with MethodicType { - override def resultType(implicit ctx: Context): Type = resType - override def underlying(implicit ctx: Context): Type = resType - protected def computeSignature(implicit ctx: Context): Signature = resultSignature - def derivedExprType(resType: Type)(implicit ctx: Context) = - if (resType eq this.resType) this else ExprType(resType) - override def computeHash = doHash(resType) - } - - final class CachedExprType(resultType: Type) extends ExprType(resultType) - - object ExprType { - def apply(resultType: Type)(implicit ctx: Context) = { - assertUnerased() - unique(new CachedExprType(resultType)) - } - } - trait TypeLambda extends LambdaType { type ThisName = TypeName type PInfo = TypeBounds - type This = TypeLambda + type This <: TypeLambda def isDependent(implicit ctx: Context): Boolean = true @@ -2679,7 +2681,10 @@ object Types { */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends CachedProxyType with TypeLambda { + extends HKLambda with TypeLambda { + + type This = PolyType + def companion = PolyType /** The bounds of the type parameters */ val paramInfos: List[TypeBounds] = paramInfosExp(this) @@ -2692,11 +2697,6 @@ object Types { override def underlying(implicit ctx: Context) = resType - def newLikeThis(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType = - PolyType.apply(paramNames)( - x => paramInfos.mapConserve(_.subst(this, x).bounds), - x => resType.subst(this, x)) - def derivedPolyType(paramNames: List[TypeName] = this.paramNames, paramInfos: List[TypeBounds] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = @@ -2730,10 +2730,9 @@ object Types { } protected def prefixString = "PolyType" - override def computeHash = doHash(paramNames, resType, paramInfos) } - object PolyType { + object PolyType extends TypeLambdaCompanion[PolyType] { def apply(paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = { @@ -2744,10 +2743,20 @@ object Types { Some((tl.typeParams, tl.resType)) def any(n: Int)(implicit ctx: Context) = - apply(tpnme.syntheticTypeParamNames(n))( + apply(syntheticParamNames(n))( pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) } + private object DepStatus { + type DependencyStatus = Byte + final val Unknown: DependencyStatus = 0 // not yet computed + final val NoDeps: DependencyStatus = 1 // no dependent parameters found + final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types + final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist + final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status + final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations + } + // ----- HK types: LambdaParam, HKApply --------------------- /** The parameter of a type lambda */ -- cgit v1.2.3 From 700e7ac6658a1d699502c94141091012d18519c4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 14:58:27 +0100 Subject: replace derived{Method,Poly}Type with derivedLambdaType --- .../src/dotty/tools/dotc/core/Denotations.scala | 8 ++++---- .../dotty/tools/dotc/core/TypeApplications.scala | 2 +- .../src/dotty/tools/dotc/core/TypeErasure.scala | 6 +++--- compiler/src/dotty/tools/dotc/core/Types.scala | 21 +++++---------------- .../tools/dotc/core/classfile/ClassfileParser.scala | 6 +++--- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 4 ++-- .../tools/dotc/transform/ElimErasedValueType.scala | 2 +- .../dotty/tools/dotc/transform/ElimRepeated.scala | 8 ++++---- .../dotty/tools/dotc/transform/ExplicitOuter.scala | 2 +- .../tools/dotc/transform/FullParameterization.scala | 2 +- .../tools/dotc/transform/ShortcutImplicits.scala | 4 ++-- .../dotty/tools/dotc/transform/SuperAccessors.scala | 4 ++-- .../src/dotty/tools/dotc/typer/Applications.scala | 2 +- .../src/dotty/tools/dotc/typer/ErrorReporting.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 2 +- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- 17 files changed, 34 insertions(+), 45 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 1d7b3c94c..7e552eda9 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -312,7 +312,7 @@ object Denotations { tp2 match { case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && tp1.isImplicit == tp2.isImplicit => - tp1.derivedMethodType( + tp1.derivedLambdaType( mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName), tp1.paramInfos, infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1))) @@ -322,7 +322,7 @@ object Denotations { case tp1: PolyType if isTerm => tp2 match { case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) => - tp1.derivedPolyType( + tp1.derivedLambdaType( mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), tp1.paramInfos, infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1))) @@ -476,7 +476,7 @@ object Denotations { case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && tp1.isImplicit == tp2.isImplicit => - tp1.derivedMethodType( + tp1.derivedLambdaType( mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName), tp1.paramInfos, tp1.resultType | tp2.resultType.subst(tp2, tp1)) case _ => @@ -485,7 +485,7 @@ object Denotations { case tp1: PolyType => tp2 match { case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) => - tp1.derivedPolyType( + tp1.derivedLambdaType( mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), tp1.paramInfos, tp1.resultType | tp2.resultType.subst(tp2, tp1)) case _ => diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 77767a38c..3a63c16db 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -429,7 +429,7 @@ class TypeApplications(val self: Type) extends AnyVal { // In this case we should always dealias since we cannot handle // higher-kinded applications to wildcard arguments. dealiased - .derivedPolyType(resType = tycon.safeDealias.appliedTo(args1)) + .derivedLambdaType(resType = tycon.safeDealias.appliedTo(args1)) .appliedTo(args) case _ => val reducer = new Reducer(dealiased, args) diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 07d613c57..8ff0be9d7 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -176,7 +176,7 @@ object TypeErasure { val erase = erasureFn(isJava, semiEraseVCs, sym.isConstructor, wildcardOK = false) def eraseParamBounds(tp: PolyType): Type = - tp.derivedPolyType( + tp.derivedLambdaType( tp.paramNames, tp.paramNames map (Function.const(TypeBounds.upper(defn.ObjectType))), tp.resultType) if (defn.isPolymorphicAfterErasure(sym)) eraseParamBounds(sym.info.asInstanceOf[PolyType]) @@ -385,9 +385,9 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean val formals = tp.paramInfos.mapConserve(paramErasure) eraseResult(tp.resultType) match { case rt: MethodType => - tp.derivedMethodType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramInfos, rt.resultType) + tp.derivedLambdaType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramInfos, rt.resultType) case rt => - tp.derivedMethodType(tp.paramNames, formals, rt) + tp.derivedLambdaType(tp.paramNames, formals, rt) } case tp @ ClassInfo(pre, cls, classParents, decls, _) => if (cls is Package) tp diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 49fc825ca..074d2e1fb 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2524,11 +2524,6 @@ object Types { override def computeSignature(implicit ctx: Context): Signature = resultSignature.prepend(paramInfos, isJava) - def derivedMethodType(paramNames: List[TermName] = this.paramNames, - paramInfos: List[Type] = this.paramInfos, - resType: Type = this.resType)(implicit ctx: Context) = - derivedLambdaType(paramNames, paramInfos, resType) - protected def prefixString = "MethodType" } @@ -2697,11 +2692,6 @@ object Types { override def underlying(implicit ctx: Context) = resType - def derivedPolyType(paramNames: List[TypeName] = this.paramNames, - paramInfos: List[TypeBounds] = this.paramInfos, - resType: Type = this.resType)(implicit ctx: Context) = - derivedLambdaType(paramNames, paramInfos, resType) - /** Merge nested polytypes into one polytype. nested polytypes are normally not supported * but can arise as temporary data structures. */ @@ -3467,12 +3457,11 @@ object Types { tp.derivedClassInfo(pre) protected def derivedJavaArrayType(tp: JavaArrayType, elemtp: Type): Type = tp.derivedJavaArrayType(elemtp) - protected def derivedMethodType(tp: MethodType, formals: List[Type], restpe: Type): Type = - tp.derivedMethodType(tp.paramNames, formals, restpe) protected def derivedExprType(tp: ExprType, restpe: Type): Type = tp.derivedExprType(restpe) - protected def derivedPolyType(tp: PolyType, pbounds: List[TypeBounds], restpe: Type): Type = - tp.derivedPolyType(tp.paramNames, pbounds, restpe) + // note: currying needed because Scala2 does not support param-dependencies + protected def derivedLambdaType(tp: LambdaType)(formals: List[tp.PInfo], restpe: Type): Type = + tp.derivedLambdaType(tp.paramNames, formals, restpe) /** Map this function over given type */ def mapOver(tp: Type): Type = { @@ -3507,7 +3496,7 @@ object Types { variance = -variance val ptypes1 = tp.paramInfos mapConserve this variance = -variance - derivedMethodType(tp, ptypes1, this(tp.resultType)) + derivedLambdaType(tp)(ptypes1, this(tp.resultType)) } mapOverMethod @@ -3519,7 +3508,7 @@ object Types { variance = -variance val bounds1 = tp.paramInfos.mapConserve(this).asInstanceOf[List[TypeBounds]] variance = -variance - derivedPolyType(tp, bounds1, this(tp.resultType)) + derivedLambdaType(tp)(bounds1, this(tp.resultType)) } mapOverPoly diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 2bb929bf3..da875c906 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -199,7 +199,7 @@ class ClassfileParser( def stripOuterParamFromConstructor() = innerClasses.get(currentClassName) match { case Some(entry) if !isStatic(entry.jflags) => val mt @ MethodTpe(paramNames, paramTypes, resultType) = denot.info - denot.info = mt.derivedMethodType(paramNames.tail, paramTypes.tail, resultType) + denot.info = mt.derivedLambdaType(paramNames.tail, paramTypes.tail, resultType) case _ => } @@ -209,7 +209,7 @@ class ClassfileParser( def normalizeConstructorInfo() = { val mt @ MethodType(paramNames) = denot.info val rt = classRoot.typeRef appliedTo (classRoot.typeParams map (_.typeRef)) - denot.info = mt.derivedMethodType(paramNames, mt.paramInfos, rt) + denot.info = mt.derivedLambdaType(paramNames, mt.paramInfos, rt) addConstructorTypeParams(denot) } @@ -975,7 +975,7 @@ class ClassfileParser( if (name == nme.CONSTRUCTOR) tpe match { case tp: MethodType => - tp.derivedMethodType(tp.paramNames, tp.paramInfos, ownerTpe) + tp.derivedLambdaType(tp.paramNames, tp.paramInfos, ownerTpe) } p = (name, tpe) values(index) = p diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index fad516da7..d34bc240f 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -65,12 +65,12 @@ object Scala2Unpickler { case _ => elemtp0 } - tp.derivedMethodType( + tp.derivedLambdaType( tp.paramNames, tp.paramInfos.init :+ defn.RepeatedParamType.appliedTo(elemtp), tp.resultType) case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramInfos, arrayToRepeated(tp.resultType)) + tp.derivedLambdaType(tp.paramNames, tp.paramInfos, arrayToRepeated(tp.resultType)) } def ensureConstructor(cls: ClassSymbol, scope: Scope)(implicit ctx: Context) = diff --git a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala index 25c01c1f7..48be02fa1 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala @@ -46,7 +46,7 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer { case tp: MethodType => val paramTypes = tp.paramInfos.mapConserve(elimEVT) val retType = elimEVT(tp.resultType) - tp.derivedMethodType(tp.paramNames, paramTypes, retType) + tp.derivedLambdaType(tp.paramNames, paramTypes, retType) case _ => tp } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index bc2674a77..683c8ac38 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -55,9 +55,9 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati val last = paramTypes.last.underlyingIfRepeated(tp.isJava) paramTypes.init :+ last } else paramTypes - tp.derivedMethodType(paramNames, paramTypes1, resultType1) + tp.derivedLambdaType(paramNames, paramTypes1, resultType1) case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramInfos, elimRepeated(tp.resultType)) + tp.derivedLambdaType(tp.paramNames, tp.paramInfos, elimRepeated(tp.resultType)) case tp => tp } @@ -139,10 +139,10 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati /** Convert type from Scala to Java varargs method */ private def toJavaVarArgs(tp: Type)(implicit ctx: Context): Type = tp match { case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramInfos, toJavaVarArgs(tp.resultType)) + tp.derivedLambdaType(tp.paramNames, tp.paramInfos, toJavaVarArgs(tp.resultType)) case tp: MethodType => val inits :+ last = tp.paramInfos val last1 = last.underlyingIfRepeated(isJava = true) - tp.derivedMethodType(tp.paramNames, inits :+ last1, tp.resultType) + tp.derivedLambdaType(tp.paramNames, inits :+ last1, tp.resultType) } } diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index f17808e62..a6e643992 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -331,7 +331,7 @@ object ExplicitOuter { def addParam(cls: ClassSymbol, tp: Type): Type = if (hasOuterParam(cls)) { val mt @ MethodTpe(pnames, ptypes, restpe) = tp - mt.derivedMethodType( + mt.derivedLambdaType( nme.OUTER :: pnames, cls.owner.enclosingClass.typeRef :: ptypes, restpe) } else tp diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index 0b9ec9085..d76a41946 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -256,7 +256,7 @@ object FullParameterization { case MethodTpe(nme.SELF :: Nil, _, restpe) => restpe.ensureMethodic.signature case info @ MethodTpe(nme.SELF :: otherNames, thisType :: otherTypes, restpe) => - info.derivedMethodType(otherNames, otherTypes, restpe).signature + info.derivedLambdaType(otherNames, otherTypes, restpe).signature case _ => Signature.NotAMethod } diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala index b5469610f..1a530b95c 100644 --- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala @@ -82,8 +82,8 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr * @return The type of the `apply` member of `implicit Ts => R`. */ private def directInfo(info: Type)(implicit ctx: Context): Type = info match { - case info: PolyType => info.derivedPolyType(resType = directInfo(info.resultType)) - case info: MethodType => info.derivedMethodType(resType = directInfo(info.resultType)) + case info: PolyType => info.derivedLambdaType(resType = directInfo(info.resultType)) + case info: MethodType => info.derivedLambdaType(resType = directInfo(info.resultType)) case info: ExprType => directInfo(info.resultType) case info => info.member(nme.apply).info } diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 102b492a8..728c1696b 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -178,7 +178,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { val accType = { def accTypeOf(tpe: Type): Type = tpe match { case tpe: PolyType => - tpe.derivedPolyType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType)) + tpe.derivedLambdaType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType)) case _ => MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0))) } @@ -230,7 +230,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { else clazz.classInfo.selfType def accTypeOf(tpe: Type): Type = tpe match { case tpe: PolyType => - tpe.derivedPolyType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType)) + tpe.derivedLambdaType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType)) case _ => MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0))) } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index ceaf3471a..236bc051e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1125,7 +1125,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case mt: ImplicitMethodType => resultTypeApprox(mt) case pt: PolyType => - pt.derivedPolyType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType)) + pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType)) case _ => tp } diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 5f9eae3da..5063a111c 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -105,7 +105,7 @@ object ErrorReporting { def whyNoMatchStr(found: Type, expected: Type) = { def dropJavaMethod(tp: Type): Type = tp match { case tp: PolyType => - tp.derivedPolyType(resType = dropJavaMethod(tp.resultType)) + tp.derivedLambdaType(resType = dropJavaMethod(tp.resultType)) case tp: JavaMethodType => MethodType(tp.paramNames, tp.paramInfos, dropJavaMethod(tp.resultType)) case tp => tp diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index cf3076fce..6ef6c12cc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -108,7 +108,7 @@ object Inliner { // Add qualifier type as leading method argument to argument `tp` def addQualType(tp: Type): Type = tp match { - case tp: PolyType => tp.derivedPolyType(tp.paramNames, tp.paramInfos, addQualType(tp.resultType)) + case tp: PolyType => tp.derivedLambdaType(tp.paramNames, tp.paramInfos, addQualType(tp.resultType)) case tp: ExprType => addQualType(tp.resultType) case tp => MethodType(qualType :: Nil, tp) } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 2dccbbcc1..a27175abd 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -444,7 +444,7 @@ object ProtoTypes { val rt = normalize(mt.resultType, pt) pt match { case pt: IgnoredProto => mt - case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramInfos, rt) + case pt: ApplyingProto => mt.derivedLambdaType(mt.paramNames, mt.paramInfos, rt) case _ => val ft = defn.FunctionOf(mt.paramInfos, rt) if (mt.paramInfos.nonEmpty || ft <:< pt) ft else rt diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index ed71f2239..14d4f315d 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -366,7 +366,7 @@ trait TypeAssigner { if (gapBuf.isEmpty) resultType1 else { val gaps = gapBuf.toList - pt.derivedPolyType( + pt.derivedLambdaType( gaps.map(paramNames), gaps.map(idx => transform(pt.paramInfos(idx)).bounds), resultType1) -- cgit v1.2.3 From 5fe6f54de36224974bdd3a9169f899f6df25971e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 15:08:59 +0100 Subject: Eliminate ParamType Replace with ParamRef --- compiler/src/dotty/tools/dotc/core/Substituters.scala | 6 +++--- compiler/src/dotty/tools/dotc/core/Types.scala | 14 ++++---------- compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala | 6 +++--- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 2 +- compiler/src/dotty/tools/dotc/transform/TreeChecker.scala | 2 +- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Substituters.scala b/compiler/src/dotty/tools/dotc/core/Substituters.scala index 23683608a..d565ec229 100644 --- a/compiler/src/dotty/tools/dotc/core/Substituters.scala +++ b/compiler/src/dotty/tools/dotc/core/Substituters.scala @@ -196,7 +196,7 @@ trait Substituters { this: Context => .mapOver(tp) } - final def substParam(tp: Type, from: ParamType, to: Type, theMap: SubstParamMap): Type = + final def substParam(tp: Type, from: ParamRef, to: Type, theMap: SubstParamMap): Type = tp match { case tp: BoundType => if (tp == from) to else tp @@ -216,7 +216,7 @@ trait Substituters { this: Context => final def substParams(tp: Type, from: BindingType, to: List[Type], theMap: SubstParamsMap): Type = tp match { - case tp: ParamType => + case tp: ParamRef => if (tp.binder == from) to(tp.paramNum) else tp case tp: NamedType => if (tp.currentSymbol.isStatic) tp @@ -269,7 +269,7 @@ trait Substituters { this: Context => def apply(tp: Type): Type = substRecThis(tp, from, to, this) } - final class SubstParamMap(from: ParamType, to: Type) extends DeepTypeMap { + final class SubstParamMap(from: ParamRef, to: Type) extends DeepTypeMap { def apply(tp: Type) = substParam(tp, from, to, this) } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 074d2e1fb..217e5e351 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1199,7 +1199,7 @@ object Types { ctx.substRecThis(this, binder, tp, null) /** Substitute a bound type by some other type */ - final def substParam(from: ParamType, to: Type)(implicit ctx: Context): Type = + final def substParam(from: ParamRef, to: Type)(implicit ctx: Context): Type = ctx.substParam(this, from, to, null) /** Substitute bound types by some other types */ @@ -2411,8 +2411,6 @@ object Types { type PInfo = Type type This <: TermLambda - def paramNames: List[TermName] - override def resultType(implicit ctx: Context): Type = if (dependencyStatus == FalseDeps) { // dealias all false dependencies val dealiasMap = new TypeMap { @@ -2831,7 +2829,7 @@ object Types { unique(new CachedHKApply(tycon, args)).checkInst } - // ----- Bound types: MethodParam, TypeParamRef -------------------------- + // ----- BoundTypes: ParamRef, RecThis ---------------------------------------- abstract class BoundType extends CachedProxyType with ValueType { type BT <: Type @@ -2839,13 +2837,9 @@ object Types { def copyBoundType(bt: BT): Type } - abstract class ParamType extends BoundType { - def paramNum: Int - def paramName: Name - } - - abstract class ParamRef extends ParamType { + abstract class ParamRef extends BoundType { type BT <: LambdaType + def paramNum: Int def paramName: binder.ThisName = binder.paramNames(paramNum) override def underlying(implicit ctx: Context): Type = { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 0b361f1f4..d712b913b 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -260,14 +260,14 @@ class TreePickler(pickler: TastyPickler) { writeByte(METHODtype) pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) case tpe: TypeParamRef => - if (!pickleParamType(tpe)) + if (!pickleParamRef(tpe)) // TODO figure out why this case arises in e.g. pickling AbstractFileReader. ctx.typerState.constraint.entry(tpe) match { case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) case _ => assert(false, s"orphan poly parameter: $tpe") } case tpe: TermParamRef => - assert(pickleParamType(tpe), s"orphan method parameter: $tpe") + assert(pickleParamRef(tpe), s"orphan method parameter: $tpe") case tpe: LazyRef => pickleType(tpe.ref) }} catch { @@ -289,7 +289,7 @@ class TreePickler(pickler: TastyPickler) { } } - def pickleParamType(tpe: ParamType)(implicit ctx: Context): Boolean = { + def pickleParamRef(tpe: ParamRef)(implicit ctx: Context): Boolean = { val binder = pickledTypes.get(tpe.binder) val pickled = binder != null if (pickled) { diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 89e935bd5..dd060ea09 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -460,7 +460,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder new api.Annotated(apiType(tpe), Array(apiAnnotation(annot))) case tp: ThisType => apiThis(tp.cls) - case tp: ParamType => + case tp: ParamRef => // TODO: Distinguishing parameters based on their names alone is not enough, // the binder is also needed (at least for type lambdas). new api.ParameterRef(tp.paramName.toString) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index dde037938..ebb5b605b 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -296,7 +296,7 @@ class TreeChecker extends Phase with SymTransformer { definedBinders += tp mapOver(tp) definedBinders -= tp - case tp: ParamType => + case tp: ParamRef => assert(definedBinders.contains(tp.binder), s"orphan param: $tp") case tp: TypeVar => apply(tp.underlying) -- cgit v1.2.3 From 4bfc17365518e6014895ae1aaa51517648b46df2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 15:12:02 +0100 Subject: Eliminate MethodOrPoly Replace with LambdaType --- compiler/src/dotty/tools/dotc/core/Types.scala | 4 +--- compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 217e5e351..fc0569e6f 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2335,8 +2335,6 @@ object Types { } } - trait MethodOrPoly extends MethodicType - /** The lambda type square: * * LambdaType | TermLambda | TypeLambda @@ -2344,7 +2342,7 @@ object Types { * HKLambda | HKTermLambda | HKTypeLambda * StarLambda | MethodType | PolyType */ - trait LambdaType extends BindingType with MethodOrPoly { self => + trait LambdaType extends BindingType with MethodicType { self => type ThisName <: Name type PInfo <: Type type This <: LambdaType{type PInfo = self.PInfo} diff --git a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala index ddd414417..ab24e1720 100644 --- a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala @@ -86,7 +86,7 @@ class VCInlineMethods extends MiniPhaseTransform with IdentityDenotTransformer { * by a call to the corresponding extension method, otherwise return it as is. */ private def rewireIfNeeded(tree: Tree)(implicit ctx: Context) = tree.tpe.widen match { - case tp: MethodOrPoly => + case tp: LambdaType => tree // The rewiring will be handled by a fully-applied parent node case _ => if (isMethodWithExtension(tree.symbol)) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 236bc051e..cd7c7fd66 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1059,7 +1059,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramInfos map repeatedToSingle else tp1.paramInfos isApplicable(alt2, formals1, WildcardType) || - tp1.paramInfos.isEmpty && tp2.isInstanceOf[MethodOrPoly] + tp1.paramInfos.isEmpty && tp2.isInstanceOf[LambdaType] case tp1: PolyType => // (2) val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags, tp1.instantiateBounds) isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 145410f65..37f43f21c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1741,7 +1741,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context): Tree = /*>|>*/ track("adapt") /*<|<*/ { /*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ { if (tree.isDef) interpolateUndetVars(tree, tree.symbol) - else if (!tree.tpe.widen.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol) + else if (!tree.tpe.widen.isInstanceOf[LambdaType]) interpolateUndetVars(tree, NoSymbol) tree.overwriteType(tree.tpe.simplified) adaptInterpolated(tree, pt, original) } -- cgit v1.2.3 From d0823efe3ecdc0b38678e58e7de4cf2139cec847 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 15:31:42 +0100 Subject: Add HKTypeLambda --- compiler/src/dotty/tools/dotc/core/Types.scala | 45 +++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index fc0569e6f..be9f310b9 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2397,6 +2397,7 @@ object Types { abstract class HKLambda extends CachedProxyType with LambdaType { final override def computeHash = doHash(paramNames, resType, paramInfos) + final override def underlying(implicit ctx: Context) = resType } abstract class StarLambda extends CachedGroundType with LambdaType with TermType { @@ -2657,6 +2658,30 @@ object Types { } } + class HKTypeLambda(val paramNames: List[TypeName])( + paramInfosExp: HKTypeLambda => List[TypeBounds], resultTypeExp: HKTypeLambda => Type) + extends HKLambda with TypeLambda { + type This = HKTypeLambda + def companion = HKTypeLambda + + val paramInfos: List[TypeBounds] = paramInfosExp(this) + val resType: Type = resultTypeExp(this) + + assert(resType.isInstanceOf[TermType], this) + assert(paramNames.nonEmpty) + + /** The type `[tparams := paramRefs] tp`, where `tparams` can be + * either a list of type parameter symbols or a list of lambda parameters + */ + def lifted(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type = + tparams match { + case LambdaParam(poly, _) :: _ => tp.subst(poly, this) + case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs) + } + + protected def prefixString = "HKTypeLambda" + } + /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T` * This is used both as a type of a polymorphic method and as a type of * a higher-kinded type parameter. Variances are encoded in parameter @@ -2677,17 +2702,12 @@ object Types { type This = PolyType def companion = PolyType - /** The bounds of the type parameters */ val paramInfos: List[TypeBounds] = paramInfosExp(this) - - /** The result type of a PolyType / body of a type lambda */ val resType: Type = resultTypeExp(this) assert(resType.isInstanceOf[TermType], this) assert(paramNames.nonEmpty) - override def underlying(implicit ctx: Context) = resType - /** Merge nested polytypes into one polytype. nested polytypes are normally not supported * but can arise as temporary data structures. */ @@ -2718,6 +2738,21 @@ object Types { protected def prefixString = "PolyType" } + object HKTypeLambda extends TypeLambdaCompanion[HKTypeLambda] { + def apply(paramNames: List[TypeName])( + paramInfosExp: HKTypeLambda => List[TypeBounds], + resultTypeExp: HKTypeLambda => Type)(implicit ctx: Context): HKTypeLambda = { + unique(new HKTypeLambda(paramNames)(paramInfosExp, resultTypeExp)) + } + + def unapply(tl: HKTypeLambda): Some[(List[LambdaParam], Type)] = + Some((tl.typeParams, tl.resType)) + + def any(n: Int)(implicit ctx: Context) = + apply(syntheticParamNames(n))( + pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) + } + object PolyType extends TypeLambdaCompanion[PolyType] { def apply(paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], -- cgit v1.2.3 From 26497bb3c654e294a48db2098978bc77b11f2889 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Mar 2017 15:51:19 +0100 Subject: Rename PolyTypeTree -> LambdaTypeTree --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 4 ++-- compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 2 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 18 +++++++-------- compiler/src/dotty/tools/dotc/ast/tpd.scala | 4 ++-- compiler/src/dotty/tools/dotc/ast/untpd.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Types.scala | 26 +++++++++++----------- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- .../src/dotty/tools/dotc/parsing/Parsers.scala | 2 +- .../dotty/tools/dotc/printing/RefinedPrinter.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/Namer.scala | 6 ++--- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 12 +++++----- 13 files changed, 44 insertions(+), 44 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 10b522eaa..6abcf6fff 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -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 } diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index b00d7df71..037ab73af 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 669e5429c..0fc47a8a4 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -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 */ @@ -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] @@ -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 @@ -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) => @@ -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) => diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 8e76d981d..ff66c8c8e 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index a5feecc77..7a9f2fe66 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -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) @@ -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. diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index be9f310b9..6c9046c20 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -103,7 +103,7 @@ object Types { final def isValueType: Boolean = this.isInstanceOf[ValueType] /** Is the is value type or type lambda? */ - final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[PolyType] + final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[TypeLambda] /** Does this type denote a stable reference (i.e. singleton type)? */ @tailrec final def isStable(implicit ctx: Context): Boolean = stripTypeVar match { @@ -541,7 +541,7 @@ object Types { } def goApply(tp: HKApply) = tp.tycon match { - case tl: PolyType => + case tl: TypeLambda => go(tl.resType).mapInfo(info => tl.derivedLambdaAbstraction(tl.paramNames, tl.paramInfos, info).appliedTo(tp.args)) case _ => @@ -1090,14 +1090,14 @@ object Types { /** The parameter types of a PolyType or MethodType, Empty list for others */ final def paramInfoss(implicit ctx: Context): List[List[Type]] = this match { case mt: MethodType => mt.paramInfos :: mt.resultType.paramInfoss - case pt: PolyType => pt.resultType.paramInfoss + case pt: TypeLambda => pt.resultType.paramInfoss case _ => Nil } /** The parameter names of a PolyType or MethodType, Empty list for others */ final def paramNamess(implicit ctx: Context): List[List[TermName]] = this match { case mt: MethodType => mt.paramNames :: mt.resultType.paramNamess - case pt: PolyType => pt.resultType.paramNamess + case pt: TypeLambda => pt.resultType.paramNamess case _ => Nil } @@ -1105,18 +1105,18 @@ object Types { /** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */ final def firstParamTypes(implicit ctx: Context): List[Type] = this match { case mt: MethodType => mt.paramInfos - case pt: PolyType => pt.resultType.firstParamTypes + case pt: TypeLambda => pt.resultType.firstParamTypes case _ => Nil } /** Is this either not a method at all, or a parameterless method? */ final def isParameterless(implicit ctx: Context): Boolean = this match { case mt: MethodType => false - case pt: PolyType => pt.resultType.isParameterless + case pt: TypeLambda => pt.resultType.isParameterless case _ => true } - /** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */ + /** The resultType of a LambdaType, or ExprType, the type itself for others */ def resultType(implicit ctx: Context): Type = this /** The final result type of a PolyType, MethodType, or ExprType, after skipping @@ -1360,7 +1360,7 @@ object Types { } /** A marker trait for types that bind other types that refer to them. - * Instances are: PolyType, MethodType, RefinedType. + * Instances are: LambdaType, RecType. */ trait BindingType extends Type @@ -2804,7 +2804,7 @@ object Types { override def superType(implicit ctx: Context): Type = { if (ctx.period != validSuper) { cachedSuper = tycon match { - case tp: PolyType => defn.AnyType + case tp: TypeLambda => defn.AnyType case tp: TypeVar if !tp.inst.exists => // supertype not stable, since underlying might change return tp.underlying.applyIfParameterized(args) @@ -2830,7 +2830,7 @@ object Types { def typeParams(implicit ctx: Context): List[ParamInfo] = { val tparams = tycon.typeParams - if (tparams.isEmpty) PolyType.any(args.length).typeParams else tparams + if (tparams.isEmpty) HKTypeLambda.any(args.length).typeParams else tparams } def derivedAppliedType(tycon: Type, args: List[Type])(implicit ctx: Context): Type = @@ -2843,7 +2843,7 @@ object Types { def check(tycon: Type): Unit = tycon.stripTypeVar match { case tycon: TypeRef if !tycon.symbol.isClass => case _: TypeParamRef | _: ErrorType | _: WildcardType => - case _: PolyType => + case _: TypeLambda => assert(args.exists(_.isInstanceOf[TypeBounds]), s"unreduced type apply: $this") case tycon: AnnotatedType => check(tycon.underlying) @@ -3530,7 +3530,7 @@ object Types { case tp: ExprType => derivedExprType(tp, this(tp.resultType)) - case tp: PolyType => + case tp: TypeLambda => def mapOverPoly = { variance = -variance val bounds1 = tp.paramInfos.mapConserve(this).asInstanceOf[List[TypeBounds]] @@ -3755,7 +3755,7 @@ object Types { case ExprType(restpe) => this(x, restpe) - case tp: PolyType => + case tp: TypeLambda => variance = -variance val y = foldOver(x, tp.paramInfos) variance = -variance diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index d712b913b..3ab984209 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -553,7 +553,7 @@ class TreePickler(pickler: TastyPickler) { case Annotated(tree, annot) => writeByte(ANNOTATEDtpt) withLength { pickleTree(tree); pickleTree(annot.tree) } - case PolyTypeTree(tparams, body) => + case LambdaTypeTree(tparams, body) => writeByte(POLYtpt) withLength { pickleParams(tparams); pickleTree(body) } case TypeBoundsTree(lo, hi) => diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index c4ff3898c..db3ca83b9 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1037,7 +1037,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle val localCtx = localNonClassCtx val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) val body = readTpt()(localCtx) - PolyTypeTree(tparams, body) + LambdaTypeTree(tparams, body) case TYPEBOUNDStpt => TypeBoundsTree(readTpt(), readTpt()) case _ => diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 9864281a5..3e3673e5e 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -728,7 +728,7 @@ object Parsers { val start = in.offset val tparams = typeParamClause(ParamOwner.TypeParam) if (in.token == ARROW) - atPos(start, in.skipToken())(PolyTypeTree(tparams, typ())) + atPos(start, in.skipToken())(LambdaTypeTree(tparams, typ())) else { accept(ARROW); typ() } } else infixType() diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 488e66d8d..76bce7920 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -401,7 +401,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { toTextLocal(tpt) ~ " " ~ blockText(refines) case AppliedTypeTree(tpt, args) => toTextLocal(tpt) ~ "[" ~ Text(args map argText, ", ") ~ "]" - case PolyTypeTree(tparams, body) => + case LambdaTypeTree(tparams, body) => changePrec(GlobalPrec) { tparamsText(tparams) ~ " -> " ~ toText(body) } @@ -451,7 +451,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { (if (tree.hasType && ctx.settings.verbose.value) i"[decls = ${tree.symbol.info.decls}]" else "") case rhs: TypeBoundsTree => typeDefText(tparamsTxt, toText(rhs)) - case PolyTypeTree(tparams, body) => + case LambdaTypeTree(tparams, body) => recur(body, tparamsText(tparams)) case rhs => typeDefText(tparamsTxt, optText(rhs)(" = " ~ _)) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 3c00d6598..54e9af593 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -298,7 +298,7 @@ class Namer { typer: Typer => val inSuperCall1 = if (tree.mods is ParamOrAccessor) EmptyFlags else inSuperCall // suppress inSuperCall for constructor parameters val higherKinded = tree match { - case TypeDef(_, PolyTypeTree(_, _)) if isDeferred => HigherKinded + case TypeDef(_, LambdaTypeTree(_, _)) if isDeferred => HigherKinded case _ => EmptyFlags } @@ -795,7 +795,7 @@ class Namer { typer: Typer => myTypeParams = { implicit val ctx = nestedCtx val tparams = original.rhs match { - case PolyTypeTree(tparams, _) => tparams + case LambdaTypeTree(tparams, _) => tparams case _ => Nil } completeParams(tparams) @@ -1169,7 +1169,7 @@ class Namer { typer: Typer => val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree] val rhs = tdef.rhs match { - case PolyTypeTree(_, body) => body + case LambdaTypeTree(_, body) => body case rhs => rhs } val rhsBodyType = typedAheadType(rhs).tpe diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 14d4f315d..0edb22b06 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -459,7 +459,7 @@ trait TypeAssigner { tree.withType(ownType) } - def assignType(tree: untpd.PolyTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) = + def assignType(tree: untpd.LambdaTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) = tree.withType(body.tpe.LambdaAbstract(tparamDefs.map(_.symbol))) def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) = diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 37f43f21c..8bde5e4e3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1096,12 +1096,12 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } } - def typedPolyTypeTree(tree: untpd.PolyTypeTree)(implicit ctx: Context): Tree = track("typedPolyTypeTree") { - val PolyTypeTree(tparams, body) = tree + def typedLambdaTypeTree(tree: untpd.LambdaTypeTree)(implicit ctx: Context): Tree = track("typedLambdaTypeTree") { + val LambdaTypeTree(tparams, body) = tree indexAndAnnotate(tparams) val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef]) val body1 = typedType(tree.body) - assignType(cpy.PolyTypeTree(tree)(tparams1, body1), tparams1, body1) + assignType(cpy.LambdaTypeTree(tree)(tparams1, body1), tparams1, body1) } def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(implicit ctx: Context): ByNameTypeTree = track("typedByNameTypeTree") { @@ -1262,10 +1262,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val TypeDef(name, rhs) = tdef completeAnnotations(tdef, sym) val rhs1 = tdef.rhs match { - case rhs @ PolyTypeTree(tparams, body) => + case rhs @ LambdaTypeTree(tparams, body) => val tparams1 = tparams.map(typed(_)).asInstanceOf[List[TypeDef]] val body1 = typedType(body) - assignType(cpy.PolyTypeTree(rhs)(tparams1, body1), tparams1, body1) + assignType(cpy.LambdaTypeTree(rhs)(tparams1, body1), tparams1, body1) case rhs => typedType(rhs) } @@ -1555,7 +1555,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case tree: untpd.OrTypeTree => typedOrTypeTree(tree) case tree: untpd.RefinedTypeTree => typedRefinedTypeTree(tree) case tree: untpd.AppliedTypeTree => typedAppliedTypeTree(tree) - case tree: untpd.PolyTypeTree => typedPolyTypeTree(tree)(localContext(tree, NoSymbol).setNewScope) + case tree: untpd.LambdaTypeTree => typedLambdaTypeTree(tree)(localContext(tree, NoSymbol).setNewScope) case tree: untpd.ByNameTypeTree => typedByNameTypeTree(tree) case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree) case tree: untpd.Alternative => typedAlternative(tree, pt) -- cgit v1.2.3 From db4f7a19c9329d59da09a4de6b8476b4b6988cdf Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 18 Mar 2017 11:26:59 +0100 Subject: Further refactorings - Use TypeLambda instead of PolyType. - Further harmonize factory operations --- .../src/dotty/tools/dotc/core/Constraint.scala | 8 +- .../dotty/tools/dotc/core/ConstraintHandling.scala | 22 ++--- .../dotty/tools/dotc/core/OrderingConstraint.scala | 14 +-- compiler/src/dotty/tools/dotc/core/ParamInfo.scala | 12 ++- .../src/dotty/tools/dotc/core/SymDenotations.scala | 2 +- compiler/src/dotty/tools/dotc/core/Symbols.scala | 6 +- .../dotty/tools/dotc/core/TypeApplications.scala | 39 ++++---- .../src/dotty/tools/dotc/core/TypeComparer.scala | 32 +++--- compiler/src/dotty/tools/dotc/core/Types.scala | 108 +++++++++++---------- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 4 +- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 4 +- .../dotty/tools/dotc/printing/PlainPrinter.scala | 4 +- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 6 +- .../src/dotty/tools/dotc/typer/Applications.scala | 9 +- compiler/src/dotty/tools/dotc/typer/Checking.scala | 8 +- .../dotty/tools/dotc/typer/ErrorReporting.scala | 2 +- .../src/dotty/tools/dotc/typer/Implicits.scala | 6 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Namer.scala | 4 +- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- 21 files changed, 150 insertions(+), 146 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala index 7a0e6dece..a6c21c0d1 100644 --- a/compiler/src/dotty/tools/dotc/core/Constraint.scala +++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala @@ -14,7 +14,7 @@ import config.Printers.constr * over values of the following types: * * - TypeLambda A constraint constrains the type parameters of a set of TypeLambdas - * - TypeParamRef The parameters of the constrained polytypes + * - TypeParamRef The parameters of the constrained type lambdas * - TypeVar Every constrained parameter might be associated with a TypeVar * that has the TypeParamRef as origin. */ @@ -120,10 +120,10 @@ abstract class Constraint extends Showable { /** A new constraint with all entries coming from `pt` removed. */ def remove(pt: TypeLambda)(implicit ctx: Context): This - /** The polytypes constrained by this constraint */ - def domainPolys: List[TypeLambda] + /** The type lambdas constrained by this constraint */ + def domainLambdas: List[TypeLambda] - /** The polytype parameters constrained by this constraint */ + /** The type lambda parameters constrained by this constraint */ def domainParams: List[TypeParamRef] /** Check whether predicate holds for all parameters in constraint */ diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index ab176b632..64621ec94 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -42,10 +42,10 @@ trait ConstraintHandling { */ protected var homogenizeArgs = false - /** We are currently comparing polytypes. Used as a flag for + /** We are currently comparing type lambdas. Used as a flag for * optimization: when `false`, no need to do an expensive `pruneLambdaParams` */ - protected var comparedPolyTypes: Set[PolyType] = Set.empty + protected var comparedTypeLambdas: Set[TypeLambda] = Set.empty private def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean): Boolean = !constraint.contains(param) || { @@ -306,21 +306,21 @@ trait ConstraintHandling { if (e.exists) e.bounds else param.binder.paramInfos(param.paramNum) } - /** Add polytype `pt`, possibly with type variables `tvars`, to current constraint + /** Add type lambda `tl`, possibly with type variables `tvars`, to current constraint * and propagate all bounds. * @param tvars See Constraint#add */ - def addToConstraint(pt: PolyType, tvars: List[TypeVar]): Unit = + def addToConstraint(tl: TypeLambda, tvars: List[TypeVar]): Unit = assert { - checkPropagated(i"initialized $pt") { - constraint = constraint.add(pt, tvars) - pt.paramNames.indices.forall { i => - val param = TypeParamRef(pt, i) + checkPropagated(i"initialized $tl") { + constraint = constraint.add(tl, tvars) + tl.paramNames.indices.forall { i => + val param = TypeParamRef(tl, i) val bounds = constraint.nonParamBounds(param) val lower = constraint.lower(param) val upper = constraint.upper(param) if (lower.nonEmpty && !bounds.lo.isRef(defn.NothingClass) || - upper.nonEmpty && !bounds.hi.isRef(defn.AnyClass)) constr.println(i"INIT*** $pt") + upper.nonEmpty && !bounds.hi.isRef(defn.AnyClass)) constr.println(i"INIT*** $tl") lower.forall(addOneBound(_, bounds.hi, isUpper = true)) && upper.forall(addOneBound(_, bounds.lo, isUpper = false)) } @@ -357,10 +357,10 @@ trait ConstraintHandling { * missing. */ def pruneLambdaParams(tp: Type) = - if (comparedPolyTypes.nonEmpty) { + if (comparedTypeLambdas.nonEmpty) { val approx = new ApproximatingTypeMap { def apply(t: Type): Type = t match { - case t @ TypeParamRef(pt: PolyType, n) if comparedPolyTypes contains pt => + case t @ TypeParamRef(pt: TypeLambda, n) if comparedTypeLambdas contains pt => val effectiveVariance = if (fromBelow) -variance else variance val bounds = pt.paramInfos(n) if (effectiveVariance > 0) bounds.lo diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 2dff39c37..84b0bfc6d 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -112,17 +112,17 @@ import OrderingConstraint._ * @param boundsMap a map from TypeLambda to arrays. * Each array contains twice the number of entries as there a type parameters * in the TypeLambda. The first half of the array contains the type bounds that constrain the - * polytype's type parameters. The second half might contain type variables that + * lambda's type parameters. The second half might contain type variables that * track the corresponding parameters, or is left empty (filled with nulls). * An instantiated type parameter is represented by having its instance type in * the corresponding array entry. The dual use of arrays for poly params * and typevars is to save space and hopefully gain some speed. * * @param lowerMap a map from TypeLambdas to arrays. Each array entry corresponds - * to a parameter P of the polytype; it contains all constrained parameters + * to a parameter P of the type lambda; it contains all constrained parameters * Q that are known to be smaller than P, i.e. Q <: P. * @param upperMap a map from TypeLambdas to arrays. Each array entry corresponds - * to a parameter P of the polytype; it contains all constrained parameters + * to a parameter P of the type lambda; it contains all constrained parameters * Q that are known to be greater than P, i.e. P <: Q. */ class OrderingConstraint(private val boundsMap: ParamBounds, @@ -456,7 +456,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ---------- Exploration -------------------------------------------------------- - def domainPolys: List[TypeLambda] = boundsMap.keys + def domainLambdas: List[TypeLambda] = boundsMap.keys def domainParams: List[TypeParamRef] = for { @@ -584,7 +584,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, val uninstVarsText = " uninstVars = " ~ Text(uninstVars map (_.toText(printer)), ", ") ~ ";" val constrainedText = - " constrained types = " ~ Text(domainPolys map (_.toText(printer)), ", ") + " constrained types = " ~ Text(domainLambdas map (_.toText(printer)), ", ") val boundsText = " bounds = " ~ { val assocs = @@ -614,8 +614,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds, case _ =>" := " + tp } val constrainedText = - " constrained types = " + domainPolys.mkString("\n") - val boundsText = + " constrained types = " + domainLambdas.mkString("\n") + val boundsText = domainLambdas " bounds = " + { val assocs = for (param <- domainParams) diff --git a/compiler/src/dotty/tools/dotc/core/ParamInfo.scala b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala index f824c3e9c..46e378fc2 100644 --- a/compiler/src/dotty/tools/dotc/core/ParamInfo.scala +++ b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala @@ -1,21 +1,23 @@ package dotty.tools.dotc.core -import Names.TypeName +import Names.Name import Contexts.Context -import Types.{Type, TypeBounds} +import Types.Type /** A common super trait of Symbol and LambdaParam. * Used to capture the attributes of type parameters which can be implemented as either. */ trait ParamInfo { + type ThisName <: Name + /** Is this the info of a type parameter? Will return `false` for symbols * that are not type parameters. */ def isTypeParam(implicit ctx: Context): Boolean /** The name of the type parameter */ - def paramName(implicit ctx: Context): TypeName + def paramName(implicit ctx: Context): ThisName /** The info of the type parameter */ def paramInfo(implicit ctx: Context): Type @@ -37,4 +39,8 @@ trait ParamInfo { /** A type that refers to the parameter */ def paramRef(implicit ctx: Context): Type +} + +object ParamInfo { + type Of[N] = ParamInfo { type ThisName = N } } \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index c126b5500..0ce61de95 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1146,7 +1146,7 @@ object SymDenotations { case tp: NamedType => hasSkolems(tp.prefix) case tp: RefinedType => hasSkolems(tp.parent) || hasSkolems(tp.refinedInfo) case tp: RecType => hasSkolems(tp.parent) - case tp: PolyType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) + case tp: TypeLambda => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) case tp: MethodType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) case tp: ExprType => hasSkolems(tp.resType) case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 705b2c133..a3c8e54b2 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -513,11 +513,11 @@ object Symbols { */ def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition - // ParamInfo methods + // ParamInfo types and methods def isTypeParam(implicit ctx: Context) = denot.is(TypeParam) - def paramName(implicit ctx: Context) = name.asTypeName + def paramName(implicit ctx: Context) = name.asInstanceOf[ThisName] def paramInfo(implicit ctx: Context) = denot.info.bounds - def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this) + def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds def paramInfoOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter def paramVariance(implicit ctx: Context) = denot.variance def paramRef(implicit ctx: Context) = denot.typeRef diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 3a63c16db..82b184dbc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -21,6 +21,8 @@ import java.util.NoSuchElementException object TypeApplications { + type TypeParamInfo = ParamInfo.Of[TypeName] + /** Assert type is not a TypeBounds instance and return it unchanged */ val noBounds = (tp: Type) => tp match { case tp: TypeBounds => throw new AssertionError("no TypeBounds allowed") @@ -47,14 +49,14 @@ object TypeApplications { /** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`? */ - def varianceConforms(tparam1: ParamInfo, tparam2: ParamInfo)(implicit ctx: Context): Boolean = + def varianceConforms(tparam1: TypeParamInfo, tparam2: TypeParamInfo)(implicit ctx: Context): Boolean = varianceConforms(tparam1.paramVariance, tparam2.paramVariance) /** Do the variances of type parameters `tparams1` conform to the variances * of corresponding type parameters `tparams2`? * This is only the case of `tparams1` and `tparams2` have the same length. */ - def variancesConform(tparams1: List[ParamInfo], tparams2: List[ParamInfo])(implicit ctx: Context): Boolean = + def variancesConform(tparams1: List[TypeParamInfo], tparams2: List[TypeParamInfo])(implicit ctx: Context): Boolean = tparams1.corresponds(tparams2)(varianceConforms) /** Extractor for @@ -73,7 +75,7 @@ object TypeApplications { } def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = tp match { - case tp @ PolyType(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) + case tp @ PolyType/*###*/(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) case _ => None } } @@ -96,7 +98,7 @@ object TypeApplications { refinements = rt :: refinements tycon = rt.parent.stripTypeVar } - def collectArgs(tparams: List[ParamInfo], + def collectArgs(tparams: List[TypeParamInfo], refinements: List[RefinedType], argBuf: mutable.ListBuffer[Type]): Option[(Type, List[Type])] = refinements match { case Nil if tparams.isEmpty && argBuf.nonEmpty => @@ -117,7 +119,7 @@ object TypeApplications { /** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK */ - def EtaExpandIfHK(tparams: List[ParamInfo], args: List[Type])(implicit ctx: Context): List[Type] = + def EtaExpandIfHK(tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): List[Type] = if (tparams.isEmpty) args else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramInfoOrCompleter)) @@ -160,7 +162,7 @@ object TypeApplications { * result type. Using this mode, we can guarantee that `appliedTo` will never * produce a higher-kinded application with a type lambda as type constructor. */ - class Reducer(tycon: PolyType, args: List[Type])(implicit ctx: Context) extends TypeMap { + class Reducer(tycon: TypeLambda, args: List[Type])(implicit ctx: Context) extends TypeMap { private var available = (0 until args.length).toSet var allReplaced = true def hasWildcardArg(p: TypeParamRef) = @@ -209,11 +211,11 @@ class TypeApplications(val self: Type) extends AnyVal { * with the bounds on its hk args. See `LambdaAbstract`, where these * types get introduced, and see `isBoundedLambda` below for the test. */ - final def typeParams(implicit ctx: Context): List[ParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ { + final def typeParams(implicit ctx: Context): List[TypeParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ { self match { case self: ClassInfo => self.cls.typeParams - case self: PolyType => + case self: TypeLambda => self.typeParams case self: TypeRef => val tsym = self.symbol @@ -236,7 +238,7 @@ class TypeApplications(val self: Type) extends AnyVal { } /** If `self` is a higher-kinded type, its type parameters, otherwise Nil */ - final def hkTypeParams(implicit ctx: Context): List[ParamInfo] = + final def hkTypeParams(implicit ctx: Context): List[TypeParamInfo] = if (isHK) typeParams else Nil /** If `self` is a generic class, its type parameter symbols, otherwise Nil */ @@ -251,7 +253,7 @@ class TypeApplications(val self: Type) extends AnyVal { def isHK(implicit ctx: Context): Boolean = self.dealias match { case self: TypeRef => self.info.isHK case self: RefinedType => false - case self: PolyType => true + case self: TypeLambda => true case self: SingletonType => false case self: TypeVar => // Using `origin` instead of `underlying`, as is done for typeParams, @@ -274,16 +276,9 @@ class TypeApplications(val self: Type) extends AnyVal { * * type T[X] = U becomes type T = [X] -> U * type T[X] >: L <: U becomes type T >: L <: ([X] -> U) - * - * TODO: Handle parameterized lower bounds */ - def LambdaAbstract(tparams: List[ParamInfo])(implicit ctx: Context): Type = { - def nameWithVariance(tparam: ParamInfo) = - tparam.paramName.withVariance(tparam.paramVariance) - def expand(tp: Type) = - PolyType(tparams.map(nameWithVariance))( - tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds), - tl => tl.lifted(tparams, tp)) + def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = { + def expand(tp: Type) = PolyType/*HKTypeLambda*/.fromParams(tparams, tp) if (tparams.isEmpty) self else self match { case self: TypeAlias => @@ -363,10 +358,10 @@ class TypeApplications(val self: Type) extends AnyVal { if (hkParams.isEmpty) self else { def adaptArg(arg: Type): Type = arg match { - case arg @ PolyType(tparams, body) if + case arg @ PolyType(tparams, body) if /*###*/ !tparams.corresponds(hkParams)(_.paramVariance == _.paramVariance) && tparams.corresponds(hkParams)(varianceConforms) => - PolyType( + PolyType(/*###*/ (tparams, hkParams).zipped.map((tparam, hkparam) => tparam.paramName.withVariance(hkparam.paramVariance)))( tl => arg.paramInfos.map(_.subst(arg, tl).bounds), @@ -410,7 +405,7 @@ class TypeApplications(val self: Type) extends AnyVal { val dealiased = stripped.safeDealias if (args.isEmpty || ctx.erasedTypes) self else dealiased match { - case dealiased: PolyType => + case dealiased: TypeLambda => def tryReduce = if (!args.exists(_.isInstanceOf[TypeBounds])) { val followAlias = Config.simplifyApplications && { diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index a4ea1d28f..7698986d5 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -428,9 +428,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { compareRec case tp2 @ HKApply(tycon2, args2) => compareHkApply2(tp1, tp2, tycon2, args2) - case tp2 @ PolyType(tparams2, body2) => + case tp2 @ PolyType(tparams2, body2) =>/*###*/ def compareHkLambda: Boolean = tp1.stripTypeVar match { - case tp1 @ PolyType(tparams1, body1) => + case tp1 @ PolyType(tparams1, body1) =>/*###*/ /* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail * The issue is that, logically, bounds should compare contravariantly, * but that would invalidate a pattern exploited in t2994: @@ -448,14 +448,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { ctx.scala2Mode || tparams1.corresponds(tparams2)((tparam1, tparam2) => isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo)) - val saved = comparedPolyTypes - comparedPolyTypes += tp1 - comparedPolyTypes += tp2 + val saved = comparedTypeLambdas + comparedTypeLambdas += tp1 + comparedTypeLambdas += tp2 try variancesConform(tparams1, tparams2) && boundsOK && isSubType(body1, body2.subst(tp2, tp1)) - finally comparedPolyTypes = saved + finally comparedTypeLambdas = saved case _ => if (!tp1.isHK) { tp2 match { @@ -669,8 +669,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val tparams1 = tparams1a.drop(lengthDiff) variancesConform(tparams1, tparams) && { if (lengthDiff > 0) - tycon1b = PolyType(tparams1.map(_.paramName))( - tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds), + tycon1b = PolyType(tparams1.map(_.paramName))(/*###*/ + tl => tparams1.map(tparam => tl.integrate(tparams, tparam.paramInfo).bounds), tl => tycon1a.appliedTo(args1.take(lengthDiff) ++ tparams1.indices.toList.map(TypeParamRef(tl, _)))) (ctx.mode.is(Mode.TypevarsMissContext) || @@ -783,7 +783,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * - the type parameters of `B` match one-by-one the variances of `tparams`, * - `B` satisfies predicate `p`. */ - private def testLifted(tp1: Type, tp2: Type, tparams: List[ParamInfo], p: Type => Boolean): Boolean = { + private def testLifted(tp1: Type, tp2: Type, tparams: List[TypeParamInfo], p: Type => Boolean): Boolean = { val classBounds = tp2.classSymbols def recur(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => @@ -1216,7 +1216,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Form a normalized conjunction of two types. * Note: For certain types, `&` is distributed inside the type. This holds for * all types which are not value types (e.g. TypeBounds, ClassInfo, - * ExprType, MethodType, PolyType). Also, when forming an `&`, + * ExprType, LambdaType). Also, when forming an `&`, * instantiated TypeVars are dereferenced and annotations are stripped. * Finally, refined types with the same refined name are * opportunistically merged. @@ -1245,7 +1245,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Form a normalized conjunction of two types. * Note: For certain types, `|` is distributed inside the type. This holds for * all types which are not value types (e.g. TypeBounds, ClassInfo, - * ExprType, MethodType, PolyType). Also, when forming an `|`, + * ExprType, LambdaType). Also, when forming an `|`, * instantiated TypeVars are dereferenced and annotations are stripped. * * Sometimes, the disjunction of two types cannot be formed because @@ -1280,16 +1280,16 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { else if (tparams2.isEmpty) original(tp1.appliedTo(tp1.typeParams.map(_.paramInfoAsSeenFrom(tp1))), tp2) else - PolyType( + PolyType(/*###*/ paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2) .zipped.map((pname, tparam1, tparam2) => pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))( paramInfosExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => - tl.lifted(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds & - tl.lifted(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds), + tl.integrate(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds & + tl.integrate(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds), resultTypeExp = tl => - original(tl.lifted(tparams1, tp1).appliedTo(tl.paramRefs), - tl.lifted(tparams2, tp2).appliedTo(tl.paramRefs))) + original(tl.integrate(tparams1, tp1).appliedTo(tl.paramRefs), + tl.integrate(tparams2, tp2).appliedTo(tl.paramRefs))) } /** Try to distribute `&` inside type, detect and handle conflicts diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 6c9046c20..a7401f6f9 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -65,12 +65,12 @@ object Types { * | +- ExprType * | +- AnnotatedType * | +- TypeVar - * | +- PolyType + * | +- HKLambda --------- PolyType * | * +- GroundType -+- AndType * +- OrType - * +- MethodType -----+- ImplicitMethodType - * | +- JavaMethodType + * +- MethodOrPoly ----- MethodType ---+- ImplicitMethodType + * | +- JavaMethodType * +- ClassInfo * | * +- NoType @@ -814,6 +814,12 @@ object Types { */ def stripAnnots(implicit ctx: Context): Type = this + /** Strip PolyType prefix */ + def stripPoly(implicit ctx: Context): Type = this match { + case tp: PolyType => tp.resType.stripPoly + case _ => this + } + /** Widen from singleton type to its underlying non-singleton * base type by applying one or more `underlying` dereferences, * Also go from => T to T. @@ -1088,31 +1094,27 @@ object Types { } /** The parameter types of a PolyType or MethodType, Empty list for others */ - final def paramInfoss(implicit ctx: Context): List[List[Type]] = this match { + final def paramInfoss(implicit ctx: Context): List[List[Type]] = stripPoly match { case mt: MethodType => mt.paramInfos :: mt.resultType.paramInfoss - case pt: TypeLambda => pt.resultType.paramInfoss case _ => Nil } /** The parameter names of a PolyType or MethodType, Empty list for others */ - final def paramNamess(implicit ctx: Context): List[List[TermName]] = this match { + final def paramNamess(implicit ctx: Context): List[List[TermName]] = stripPoly match { case mt: MethodType => mt.paramNames :: mt.resultType.paramNamess - case pt: TypeLambda => pt.resultType.paramNamess case _ => Nil } /** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */ - final def firstParamTypes(implicit ctx: Context): List[Type] = this match { + final def firstParamTypes(implicit ctx: Context): List[Type] = stripPoly match { case mt: MethodType => mt.paramInfos - case pt: TypeLambda => pt.resultType.firstParamTypes case _ => Nil } /** Is this either not a method at all, or a parameterless method? */ - final def isParameterless(implicit ctx: Context): Boolean = this match { + final def isParameterless(implicit ctx: Context): Boolean = stripPoly match { case mt: MethodType => false - case pt: TypeLambda => pt.resultType.isParameterless case _ => true } @@ -1122,9 +1124,8 @@ object Types { /** The final result type of a PolyType, MethodType, or ExprType, after skipping * all parameter sections, the type itself for all others. */ - def finalResultType(implicit ctx: Context): Type = resultType match { + def finalResultType(implicit ctx: Context): Type = resultType.stripPoly match { case mt: MethodType => mt.resultType.finalResultType - case pt: PolyType => pt.resultType.finalResultType case _ => resultType } @@ -2337,10 +2338,10 @@ object Types { /** The lambda type square: * - * LambdaType | TermLambda | TypeLambda - * ------------+-------------------+------------------ - * HKLambda | HKTermLambda | HKTypeLambda - * StarLambda | MethodType | PolyType + * LambdaType | TermLambda | TypeLambda + * -------------+-------------------+------------------ + * HKLambda | HKTermLambda | HKTypeLambda + * MethodOrPoly | MethodType | PolyType */ trait LambdaType extends BindingType with MethodicType { self => type ThisName <: Name @@ -2370,6 +2371,15 @@ object Types { protected def companion: LambdaTypeCompanion[ThisName, PInfo, This] + /** The type `[tparams := paramRefs] tp`, where `tparams` can be + * either a list of type parameter symbols or a list of lambda parameters + */ + def integrate(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type = + tparams match { + case LambdaParam(lam, _) :: _ => tp.subst(lam, this) + case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs) + } + final def derivedLambdaType(paramNames: List[ThisName] = this.paramNames, paramInfos: List[PInfo] = this.paramInfos, resType: Type = this.resType)(implicit ctx: Context) = @@ -2400,7 +2410,7 @@ object Types { final override def underlying(implicit ctx: Context) = resType } - abstract class StarLambda extends CachedGroundType with LambdaType with TermType { + abstract class MethodOrPoly extends CachedGroundType with LambdaType with TermType { final override def computeHash = doHash(paramNames, resType, paramInfos) } @@ -2504,7 +2514,7 @@ object Types { abstract case class MethodType(paramNames: List[TermName])( paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends StarLambda with TermLambda with NarrowCached { thisMethodType => + extends MethodOrPoly with TermLambda with NarrowCached { thisMethodType => import MethodType._ type This = MethodType @@ -2544,14 +2554,25 @@ object Types { } abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] { - def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT def syntheticParamNames(n: Int): List[N] + + def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT def apply(paramNames: List[N], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = apply(paramNames)(_ => paramInfos, _ => resultType) def apply(paramInfos: List[PInfo])(resultTypeExp: LT => Type)(implicit ctx: Context): LT = apply(syntheticParamNames(paramInfos.length))(_ => paramInfos, resultTypeExp) def apply(paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = apply(syntheticParamNames(paramInfos.length), paramInfos, resultType) + + protected def paramName(param: ParamInfo.Of[N])(implicit ctx: Context): N = + param.paramName + protected def paramInfo(param: ParamInfo.Of[N])(implicit ctx: Context): Type = + param.paramInfo + + def fromParams[PI <: ParamInfo.Of[N]](params: List[PI], resultType: Type)(implicit ctx: Context): LT = + apply(params.map(paramName))( + tl => params.map(param => tl.integrate(params, paramInfo(param)).asInstanceOf[PInfo]), + tl => tl.integrate(params, resultType)) } abstract class TermLambdaCompanion[LT <: TermLambda] @@ -2567,10 +2588,11 @@ object Types { abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { /** Produce method type from parameter symbols, with special mappings for repeated - * and inline parameters. + * and inline parameters: + * - replace @repeated annotations on Seq or Array types by types + * - add @inlineParam to inline call-by-value parameters */ def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = { - /** Replace @repeated annotations on Seq or Array types by types */ def translateRepeated(tp: Type): Type = tp match { case tp @ ExprType(tp1) => tp.derivedExprType(translateRepeated(tp1)) case AnnotatedType(tp, annot) if annot matches defn.RepeatedAnnot => @@ -2580,21 +2602,18 @@ object Types { case tp => tp } - /** Add @inlineParam to inline call-by-value parameters */ def translateInline(tp: Type): Type = tp match { case _: ExprType => tp case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot)) } - def integrate(tp: Type, mt: MethodType): Type = - tp.subst(params, params.indices.toList.map(mt.newParamRef)) - - def paramInfo(param: Symbol): Type = { + def paramInfo(param: Symbol) = { val paramType = translateRepeated(param.info) if (param.is(Inline)) translateInline(paramType) else paramType } + apply(params.map(_.name.asTermName))( - mt => params.map(param => integrate(paramInfo(param), mt)), - mt => integrate(resultType, mt)) + tl => params.map(p => tl.integrate(params, paramInfo(p))), + tl => tl.integrate(params, resultType)) } def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = { @@ -2670,15 +2689,6 @@ object Types { assert(resType.isInstanceOf[TermType], this) assert(paramNames.nonEmpty) - /** The type `[tparams := paramRefs] tp`, where `tparams` can be - * either a list of type parameter symbols or a list of lambda parameters - */ - def lifted(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type = - tparams match { - case LambdaParam(poly, _) :: _ => tp.subst(poly, this) - case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs) - } - protected def prefixString = "HKTypeLambda" } @@ -2726,15 +2736,6 @@ object Types { case _ => this } - /** The type `[tparams := paramRefs] tp`, where `tparams` can be - * either a list of type parameter symbols or a list of lambda parameters - */ - def lifted(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type = - tparams match { - case LambdaParam(poly, _) :: _ => tp.subst(poly, this) - case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs) - } - protected def prefixString = "PolyType" } @@ -2751,6 +2752,9 @@ object Types { def any(n: Int)(implicit ctx: Context) = apply(syntheticParamNames(n))( pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) + + override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName = + param.paramName.withVariance(param.paramVariance) } object PolyType extends TypeLambdaCompanion[PolyType] { @@ -2766,6 +2770,9 @@ object Types { def any(n: Int)(implicit ctx: Context) = apply(syntheticParamNames(n))( pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) + + override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName = + param.paramName.withVariance(param.paramVariance) //### } private object DepStatus { @@ -2782,10 +2789,11 @@ object Types { /** The parameter of a type lambda */ case class LambdaParam(tl: TypeLambda, n: Int) extends ParamInfo { + type ThisName = TypeName def isTypeParam(implicit ctx: Context) = tl.paramNames.head.isTypeName - def paramName(implicit ctx: Context): TypeName = tl.paramNames(n) - def paramInfo(implicit ctx: Context): Type = tl.paramInfos(n) - def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type = paramInfo + def paramName(implicit ctx: Context) = tl.paramNames(n) + def paramInfo(implicit ctx: Context) = tl.paramInfos(n) + def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = paramInfo def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance def toArg: Type = TypeParamRef(tl, n) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 3ab984209..4c600564d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -253,7 +253,7 @@ class TreePickler(pickler: TastyPickler) { case tpe: ExprType => writeByte(BYNAMEtype) pickleType(tpe.underlying) - case tpe: PolyType => + case tpe: TypeLambda => writeByte(POLYtype) pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) case tpe: MethodType if richTypes => diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index db3ca83b9..e751e99fe 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -38,7 +38,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle /** A map from addresses of type entries to the types they define. * Currently only populated for types that might be recursively referenced - * from within themselves (i.e. RefinedTypes, PolyTypes, MethodTypes). + * from within themselves (i.e. RecTypes, LambdaTypes). */ private val typeAtAddr = new mutable.HashMap[Addr, Type] @@ -283,7 +283,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle result case PARAMtype => readTypeRef() match { - case binder: PolyType => TypeParamRef(binder, readNat()) + case binder: TypeLambda => binder.newParamRef(readNat()) case binder: MethodType => binder.newParamRef(readNat()) } case CLASSconst => diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index d34bc240f..34cbf4677 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -42,7 +42,7 @@ object Scala2Unpickler { /** Convert temp poly type to poly type and leave other types alone. */ def translateTempPoly(tp: Type)(implicit ctx: Context): Type = tp match { - case TempPolyType(tparams, restpe) => restpe.LambdaAbstract(tparams) + case TempPolyType(tparams, restpe) => restpe.LambdaAbstract(tparams) // PolyType.fromParams(tparams, restpe) case tp => tp } @@ -745,7 +745,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas TempClassInfoType(until(end, readTypeRef), symScope(clazz), clazz) case METHODtpe | IMPLICITMETHODtpe => val restpe = readTypeRef() - val params = until(end, readSymbolRef) + val params = until(end, readSymbolRef).asInstanceOf[List[TermSymbol]] def isImplicit = tag == IMPLICITMETHODtpe || params.nonEmpty && (params.head is Implicit) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 94621056f..d5014b547 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -175,7 +175,7 @@ class PlainPrinter(_ctx: Context) extends Printer { } case tp: ExprType => changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) } - case tp: PolyType => + case tp: TypeLambda => def paramText(name: Name, bounds: TypeBounds): Text = name.toString ~ toText(bounds) changePrec(GlobalPrec) { "[" ~ Text((tp.paramNames, tp.paramInfos).zipped.map(paramText), ", ") ~ @@ -216,7 +216,7 @@ class PlainPrinter(_ctx: Context) extends Printer { */ protected def simpleNameString(sym: Symbol): String = nameString(sym.name) - /** If -uniqid is set, the hashcode of the polytype, after a # */ + /** If -uniqid is set, the hashcode of the lambda type, after a # */ protected def lambdaHash(pt: LambdaType): Text = if (ctx.settings.uniqid.value) "#" + pt.hashCode else "" diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index dd060ea09..222d8af17 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -286,7 +286,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder def apiDef(sym: TermSymbol): api.Def = { def paramLists(t: Type, start: Int = 0): List[api.ParameterList] = t match { - case pt: PolyType => + case pt: TypeLambda => assert(start == 0) paramLists(pt.resultType) case mt @ MethodTpe(pnames, ptypes, restpe) => @@ -311,7 +311,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } val tparams = sym.info match { - case pt: PolyType => + case pt: TypeLambda => (pt.paramNames, pt.paramInfos).zipped.map((pname, pbounds) => apiTypeParameter(pname.toString, 0, pbounds.lo, pbounds.hi)) case _ => @@ -385,7 +385,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val apiTycon = simpleType(tycon) val apiArgs = args.map(processArg) new api.Parameterized(apiTycon, apiArgs.toArray) - case PolyType(tparams, res) => + case PolyType(tparams, res) => /*###*/ val apiTparams = tparams.map(apiTypeParameter) val apiRes = apiType(res) new api.Polymorphic(apiRes, apiTparams.toArray) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index cd7c7fd66..25c9c13d8 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -34,7 +34,7 @@ object Applications { def extractorMember(tp: Type, name: Name)(implicit ctx: Context) = { def isPossibleExtractorType(tp: Type) = tp match { - case _: MethodType | _: PolyType => false + case _: MethodOrPoly => false case _ => true } tp.member(name).suchThat(d => isPossibleExtractorType(d.info)) @@ -1412,12 +1412,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => recur(altFormals.map(_.tail), args1) case _ => } - def paramTypes(alt: Type): List[Type] = alt match { - case mt: MethodType => mt.paramInfos - case mt: PolyType => paramTypes(mt.resultType) - case _ => Nil - } - recur(alts.map(alt => paramTypes(alt.widen)), pt.args) + recur(alts.map(_.widen.firstParamTypes), pt.args) } private def harmonizeWith[T <: AnyRef](ts: List[T])(tpe: T => Type, adapt: (T, Type) => T)(implicit ctx: Context): List[T] = { diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index e959e6984..00d36651e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -50,12 +50,12 @@ object Checking { arg.pos.focus) } - /** Check that type arguments `args` conform to corresponding bounds in `poly` + /** Check that type arguments `args` conform to corresponding bounds in `tl` * Note: This does not check the bounds of AppliedTypeTrees. These * are handled by method checkBounds in FirstTransform */ - def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit = - checkBounds(args, poly.paramInfos, _.substParams(poly, _)) + def checkBounds(args: List[tpd.Tree], tl: TypeLambda)(implicit ctx: Context): Unit = + checkBounds(args, tl.paramInfos, _.substParams(tl, _)) /** Check applied type trees for well-formedness. This means * - all arguments are within their corresponding bounds @@ -82,7 +82,7 @@ object Checking { def checkWildcardHKApply(tp: Type, pos: Position): Unit = tp match { case tp @ HKApply(tycon, args) if args.exists(_.isInstanceOf[TypeBounds]) => tycon match { - case tycon: PolyType => + case tycon: TypeLambda => ctx.errorOrMigrationWarning( ex"unreducible application of higher-kinded type $tycon to wildcard arguments", pos) diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 5063a111c..6c72c16e0 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -74,7 +74,7 @@ object ErrorReporting { def anonymousTypeMemberStr(tpe: Type) = { val kind = tpe match { case _: TypeBounds => "type with bounds" - case _: PolyType | _: MethodType => "method" + case _: MethodOrPoly => "method" case _ => "value of type" } em"$kind $tpe" diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index af2145376..703d2fc3c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -108,8 +108,8 @@ object Implicits { } def discardForValueType(tpw: Type): Boolean = tpw match { - case mt: MethodType => !mt.isImplicit - case mt: PolyType => discardForValueType(tpw.resultType) + case tpw: MethodType => !tpw.isImplicit + case tpw: PolyType => discardForValueType(tpw.resultType) case _ => false } @@ -387,7 +387,7 @@ trait ImplicitRunInfo { self: RunInfo => case _ => arg } (apply(tp.tycon) /: tp.args)((tc, arg) => AndType.make(tc, applyArg(arg))) - case tp: PolyType => + case tp: TypeLambda => apply(tp.resType) case _ => mapOver(tp) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 6ef6c12cc..90052a1ed 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -120,7 +120,7 @@ object Inliner { // Abstract accessed type over local refs def abstractQualType(mtpe: Type): Type = if (localRefs.isEmpty) mtpe - else mtpe.LambdaAbstract(localRefs.map(_.symbol)).asInstanceOf[PolyType].flatten + else PolyType.fromParams(localRefs.map(_.symbol.asType), mtpe).flatten val accessorType = abstractQualType(addQualType(dealiasMap(accessedType))) val accessor = accessorSymbol(tree, accessorType).asTerm diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 54e9af593..bdf044aa8 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -113,9 +113,9 @@ trait NamerContextOps { this: Context => if (isJava) for (param <- params) if (param.info.isDirectRef(defn.ObjectClass)) param.info = defn.AnyType - make.fromSymbols(params, resultType) + make.fromSymbols(params.asInstanceOf[List[TermSymbol]], resultType) } - if (typeParams.nonEmpty) monotpe.LambdaAbstract(typeParams) + if (typeParams.nonEmpty) monotpe.LambdaAbstract(typeParams.asInstanceOf[List[TypeSymbol]]) else if (valueParamss.isEmpty) ExprType(monotpe) else monotpe } diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 0edb22b06..4416428f4 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -460,7 +460,7 @@ trait TypeAssigner { } def assignType(tree: untpd.LambdaTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) = - tree.withType(body.tpe.LambdaAbstract(tparamDefs.map(_.symbol))) + tree.withType(body.tpe.LambdaAbstract(tparamDefs.map(_.symbol.asType))) def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) = tree.withType(ExprType(result.tpe)) -- cgit v1.2.3 From c67217594bb40e1eab7e567c97bdf29ac0654864 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 18 Mar 2017 11:48:48 +0100 Subject: Eliminate LambdaAbstract Use fromParams instead. --- .../dotty/tools/dotc/core/TypeApplications.scala | 21 +--------------- compiler/src/dotty/tools/dotc/core/Types.scala | 28 ++++++++++++++++++---- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 6 +++-- compiler/src/dotty/tools/dotc/typer/Checking.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 3 ++- compiler/src/dotty/tools/dotc/typer/Namer.scala | 6 ++--- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 82b184dbc..eb3394082 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -272,25 +272,6 @@ class TypeApplications(val self: Type) extends AnyVal { self } - /** Lambda abstract `self` with given type parameters. Examples: - * - * type T[X] = U becomes type T = [X] -> U - * type T[X] >: L <: U becomes type T >: L <: ([X] -> U) - */ - def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = { - def expand(tp: Type) = PolyType/*HKTypeLambda*/.fromParams(tparams, tp) - if (tparams.isEmpty) self - else self match { - case self: TypeAlias => - self.derivedTypeAlias(expand(self.alias)) - case self @ TypeBounds(lo, hi) => - self.derivedTypeBounds( - if (lo.isRef(defn.NothingClass)) lo else expand(lo), - expand(hi)) - case _ => expand(self) - } - } - /** Convert a type constructor `TC` which has type parameters `T1, ..., Tn` * in a context where type parameters `U1,...,Un` are expected to * @@ -303,7 +284,7 @@ class TypeApplications(val self: Type) extends AnyVal { */ def EtaExpand(tparams: List[TypeSymbol])(implicit ctx: Context): Type = { val tparamsToUse = if (variancesConform(typeParams, tparams)) tparams else typeParamSymbols - self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparamsToUse) + HKTypeLambda.fromParams(tparamsToUse, self.appliedTo(tparams map (_.typeRef))) //.ensuring(res => res.EtaReduce =:= self, s"res = $res, core = ${res.EtaReduce}, self = $self, hc = ${res.hashCode}") } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index a7401f6f9..4ba0a2924 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2566,12 +2566,11 @@ object Types { protected def paramName(param: ParamInfo.Of[N])(implicit ctx: Context): N = param.paramName - protected def paramInfo(param: ParamInfo.Of[N])(implicit ctx: Context): Type = - param.paramInfo - def fromParams[PI <: ParamInfo.Of[N]](params: List[PI], resultType: Type)(implicit ctx: Context): LT = - apply(params.map(paramName))( - tl => params.map(param => tl.integrate(params, paramInfo(param)).asInstanceOf[PInfo]), + def fromParams[PI <: ParamInfo.Of[N]](params: List[PI], resultType: Type)(implicit ctx: Context): Type = + if (params.isEmpty) resultType + else apply(params.map(paramName))( + tl => params.map(param => tl.integrate(params, param.paramInfo).asInstanceOf[PInfo]), tl => tl.integrate(params, resultType)) } @@ -2755,6 +2754,25 @@ object Types { override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName = param.paramName.withVariance(param.paramVariance) + + /** Distributes Lambda inside type bounds. Examples: + * + * type T[X] = U becomes type T = [X] -> U + * type T[X] <: U becomes type T >: Nothign <: ([X] -> U) + * type T[X] >: L <: U becomes type T >: ([X] -> L) <: ([X] -> U) + */ + override def fromParams[PI <: ParamInfo.Of[TypeName]](params: List[PI], resultType: Type)(implicit ctx: Context): Type = { + def expand(tp: Type) = PolyType.fromParams(params, tp) //### + resultType match { + case rt: TypeAlias => + rt.derivedTypeAlias(expand(rt.alias)) + case rt @ TypeBounds(lo, hi) => + rt.derivedTypeBounds( + if (lo.isRef(defn.NothingClass)) lo else expand(lo), expand(hi)) + case rt => + expand(rt) + } + } } object PolyType extends TypeLambdaCompanion[PolyType] { diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 34cbf4677..cf99bb022 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -42,13 +42,15 @@ object Scala2Unpickler { /** Convert temp poly type to poly type and leave other types alone. */ def translateTempPoly(tp: Type)(implicit ctx: Context): Type = tp match { - case TempPolyType(tparams, restpe) => restpe.LambdaAbstract(tparams) // PolyType.fromParams(tparams, restpe) + case TempPolyType(tparams, restpe) => + (if (tparams.head.owner.isTerm) PolyType else HKTypeLambda) + .fromParams(tparams, restpe) case tp => tp } def addConstructorTypeParams(denot: SymDenotation)(implicit ctx: Context) = { assert(denot.isConstructor) - denot.info = denot.info.LambdaAbstract(denot.owner.typeParams) + denot.info = PolyType.fromParams(denot.owner.typeParams, denot.info) } /** Convert array parameters denoting a repeated parameter of a Java method diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 00d36651e..5d1c44efc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -76,7 +76,7 @@ object Checking { val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args val bounds = tparams.map(_.paramInfoAsSeenFrom(tycon.tpe).bounds) def instantiate(bound: Type, args: List[Type]) = - bound.LambdaAbstract(tparams).appliedTo(args) + HKTypeLambda.fromParams(tparams, bound).appliedTo(args) checkBounds(orderedArgs, bounds, instantiate) def checkWildcardHKApply(tp: Type, pos: Position): Unit = tp match { diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 90052a1ed..f6d65fbb9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -120,7 +120,8 @@ object Inliner { // Abstract accessed type over local refs def abstractQualType(mtpe: Type): Type = if (localRefs.isEmpty) mtpe - else PolyType.fromParams(localRefs.map(_.symbol.asType), mtpe).flatten + else PolyType.fromParams(localRefs.map(_.symbol.asType), mtpe) + .asInstanceOf[PolyType].flatten val accessorType = abstractQualType(addQualType(dealiasMap(accessedType))) val accessor = accessorSymbol(tree, accessorType).asTerm diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index bdf044aa8..ce2030c01 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -115,7 +115,7 @@ trait NamerContextOps { this: Context => if (param.info.isDirectRef(defn.ObjectClass)) param.info = defn.AnyType make.fromSymbols(params.asInstanceOf[List[TermSymbol]], resultType) } - if (typeParams.nonEmpty) monotpe.LambdaAbstract(typeParams.asInstanceOf[List[TypeSymbol]]) + if (typeParams.nonEmpty) PolyType.fromParams(typeParams.asInstanceOf[List[TypeSymbol]], monotpe) else if (valueParamss.isEmpty) ExprType(monotpe) else monotpe } @@ -1151,9 +1151,7 @@ class Namer { typer: Typer => } def typeDefSig(tdef: TypeDef, sym: Symbol, tparamSyms: List[TypeSymbol])(implicit ctx: Context): Type = { - def abstracted(tp: Type): Type = - if (tparamSyms.nonEmpty) tp.LambdaAbstract(tparamSyms) else tp - + def abstracted(tp: Type): Type = HKTypeLambda.fromParams(tparamSyms, tp) val dummyInfo = abstracted(TypeBounds.empty) sym.info = dummyInfo // Temporarily set info of defined type T to ` >: Nothing <: Any. diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 4416428f4..fb1728578 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -460,7 +460,7 @@ trait TypeAssigner { } def assignType(tree: untpd.LambdaTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) = - tree.withType(body.tpe.LambdaAbstract(tparamDefs.map(_.symbol.asType))) + tree.withType(HKTypeLambda.fromParams(tparamDefs.map(_.symbol.asType), body.tpe)) def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) = tree.withType(ExprType(result.tpe)) -- cgit v1.2.3 From e4d499945b93f95bbff7e9fe71aeffc9af4fc8bd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 18 Mar 2017 13:57:52 +0100 Subject: Handle hk lambdas in tasty --- .../dotty/tools/dotc/core/tasty/TastyFormat.scala | 17 +++++----- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 20 ++++++------ .../tools/dotc/core/tasty/TreeUnpickler.scala | 36 ++++++++++++---------- .../src/dotty/tools/dotc/printing/Formatting.scala | 2 +- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 98577f3c5..8b2255e94 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -151,8 +151,9 @@ Standard-Section: "ASTs" TopLevelStat* BIND Length boundName_NameRef bounds_Type // for type-variables defined in a type pattern BYNAMEtype underlying_Type - POLYtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing) + POLYtype Length result_Type NamesTypes METHODtype Length result_Type NamesTypes // needed for refinements + TYPELAMBDAtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing) PARAMtype Length binder_ASTref paramNum_Nat // needed for refinements SHARED type_ASTRef NamesTypes = NameType* @@ -345,9 +346,10 @@ object TastyFormat { final val ORtpt = 169 final val METHODtype = 170 final val POLYtype = 171 - final val POLYtpt = 172 - final val PARAMtype = 173 - final val ANNOTATION = 174 + final val TYPELAMBDAtype = 172 + final val LAMBDAtpt = 173 + final val PARAMtype = 174 + final val ANNOTATION = 175 final val firstSimpleTreeTag = UNITconst final val firstNatTreeTag = SHARED @@ -397,7 +399,7 @@ object TastyFormat { | SINGLETONtpt | REFINEDtpt | APPLIEDtpt - | POLYtpt + | LAMBDAtpt | TYPEBOUNDStpt | ANNOTATEDtpt | ANDtpt @@ -528,8 +530,9 @@ object TastyFormat { case BYNAMEtype => "BYNAMEtype" case BYNAMEtpt => "BYNAMEtpt" case POLYtype => "POLYtype" - case POLYtpt => "POLYtpt" case METHODtype => "METHODtype" + case TYPELAMBDAtype => "TYPELAMBDAtype" + case LAMBDAtpt => "LAMBDAtpt" case PARAMtype => "PARAMtype" case ANNOTATION => "ANNOTATION" case PRIVATEqualified => "PRIVATEqualified" @@ -543,7 +546,7 @@ object TastyFormat { case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND | SELFDEF | REFINEDtype => 1 case RENAMED | PARAMtype => 2 - case POLYtype | METHODtype => -1 + case POLYtype | METHODtype | TYPELAMBDAtype => -1 case _ => 0 } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 4c600564d..fc9d9c447 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -253,12 +253,12 @@ class TreePickler(pickler: TastyPickler) { case tpe: ExprType => writeByte(BYNAMEtype) pickleType(tpe.underlying) - case tpe: TypeLambda => - writeByte(POLYtype) - pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) + case tpe: HKTypeLambda => + pickleMethodic(TYPELAMBDAtype, tpe) + case tpe: PolyType /*if richTypes*/ => //### + pickleMethodic(POLYtype, tpe) case tpe: MethodType if richTypes => - writeByte(METHODtype) - pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) + pickleMethodic(METHODtype, tpe) case tpe: TypeParamRef => if (!pickleParamRef(tpe)) // TODO figure out why this case arises in e.g. pickling AbstractFileReader. @@ -281,13 +281,15 @@ class TreePickler(pickler: TastyPickler) { pickleName(qualifiedName(pkg)) } - def pickleMethodic(result: Type, names: List[Name], types: List[Type])(implicit ctx: Context) = + def pickleMethodic(tag: Int, tpe: LambdaType)(implicit ctx: Context) = { + writeByte(tag) withLength { - pickleType(result, richTypes = true) - (names, types).zipped.foreach { (name, tpe) => + pickleType(tpe.resultType, richTypes = true) + (tpe.paramNames, tpe.paramInfos).zipped.foreach { (name, tpe) => pickleName(name); pickleType(tpe) } } + } def pickleParamRef(tpe: ParamRef)(implicit ctx: Context): Boolean = { val binder = pickledTypes.get(tpe.binder) @@ -554,7 +556,7 @@ class TreePickler(pickler: TastyPickler) { writeByte(ANNOTATEDtpt) withLength { pickleTree(tree); pickleTree(annot.tree) } case LambdaTypeTree(tparams, body) => - writeByte(POLYtpt) + writeByte(LAMBDAtpt) withLength { pickleParams(tparams); pickleTree(body) } case TypeBoundsTree(lo, hi) => writeByte(TYPEBOUNDStpt) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index e751e99fe..b83045a11 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -234,6 +234,19 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle (nameReader.readParamNames(end), paramReader) } + def readMethodic[N <: Name, PInfo <: Type, LT <: LambdaType] + (companion: LambdaTypeCompanion[N, PInfo, LT], nameMap: Name => N): LT = { + val nameReader = fork + nameReader.skipTree() // skip result + val paramReader = nameReader.fork + val paramNames = nameReader.readParamNames(end).map(nameMap) + val result = companion(paramNames)( + pt => registeringType(pt, paramReader.readParamTypes[PInfo](end)), + pt => readType()) + goto(end) + result + } + val result = (tag: @switch) match { case SUPERtype => @@ -268,23 +281,14 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle registerSym(start, sym) TypeRef.withFixedSym(NoPrefix, sym.name, sym) case POLYtype => - val (paramNames, paramReader) = readNamesSkipParams - val result = PolyType(paramNames.map(_.toTypeName))( - pt => registeringType(pt, paramReader.readParamTypes[TypeBounds](end)), - pt => readType()) - goto(end) - result + readMethodic(PolyType, _.toTypeName) case METHODtype => - val (names, paramReader) = readNamesSkipParams - val result = MethodType(names.map(_.toTermName))( - mt => registeringType(mt, paramReader.readParamTypes[Type](end)), - mt => readType()) - goto(end) - result + readMethodic(MethodType, _.toTermName) + case TYPELAMBDAtype => + readMethodic(HKTypeLambda, _.toTypeName) case PARAMtype => readTypeRef() match { - case binder: TypeLambda => binder.newParamRef(readNat()) - case binder: MethodType => binder.newParamRef(readNat()) + case binder: LambdaType => binder.newParamRef(readNat()) } case CLASSconst => ConstantType(Constant(readType())) @@ -410,7 +414,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle } def isAbstractType(ttag: Int)(implicit ctx: Context): Boolean = nextUnsharedTag match { - case POLYtpt => + case LAMBDAtpt => val rdr = fork rdr.reader.readByte() // tag rdr.reader.readNat() // length @@ -1033,7 +1037,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle OrTypeTree(readTpt(), readTpt()) case ANNOTATEDtpt => Annotated(readTpt(), readTerm()) - case POLYtpt => + case LAMBDAtpt => val localCtx = localNonClassCtx val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) val body = readTpt()(localCtx) diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index e8fa45403..4a57270a4 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -31,7 +31,7 @@ object Formatting { case arg: Showable => try arg.show catch { - case NonFatal(ex) => s"[cannot display due to $ex, raw string = $toString]" + case NonFatal(ex) if false => s"[cannot display due to $ex, raw string = $toString]" } case _ => arg.toString } -- cgit v1.2.3 From 8b1340b9b73d319ef7ac8f7f3bdaa75943de277e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 18 Mar 2017 17:21:46 +0100 Subject: Generalize comparisons from PolyTypes to TypeLambdas --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 7698986d5..597b28088 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -428,9 +428,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { compareRec case tp2 @ HKApply(tycon2, args2) => compareHkApply2(tp1, tp2, tycon2, args2) - case tp2 @ PolyType(tparams2, body2) =>/*###*/ - def compareHkLambda: Boolean = tp1.stripTypeVar match { - case tp1 @ PolyType(tparams1, body1) =>/*###*/ + case tp2: TypeLambda => + def compareTypeLambda: Boolean = tp1.stripTypeVar match { + case tp1: TypeLambda if tp1.isInstanceOf[PolyType] == tp2.isInstanceOf[PolyType] => /* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail * The issue is that, logically, bounds should compare contravariantly, * but that would invalidate a pattern exploited in t2994: @@ -446,15 +446,15 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { */ def boundsOK = ctx.scala2Mode || - tparams1.corresponds(tparams2)((tparam1, tparam2) => + tp1.typeParams.corresponds(tp2.typeParams)((tparam1, tparam2) => isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo)) val saved = comparedTypeLambdas comparedTypeLambdas += tp1 comparedTypeLambdas += tp2 try - variancesConform(tparams1, tparams2) && + variancesConform(tp1.typeParams, tp2.typeParams) && boundsOK && - isSubType(body1, body2.subst(tp2, tp1)) + isSubType(tp1.resType, tp2.resType.subst(tp2, tp1)) finally comparedTypeLambdas = saved case _ => if (!tp1.isHK) { @@ -466,7 +466,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } fourthTry(tp1, tp2) } - compareHkLambda + compareTypeLambda case OrType(tp21, tp22) => // Rewrite T1 <: (T211 & T212) | T22 to T1 <: (T211 | T22) and T1 <: (T212 | T22) // and analogously for T1 <: T21 | (T221 & T222) -- cgit v1.2.3 From f6c61f3976a2780ce42ea6cd814986b662570687 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 18 Mar 2017 18:46:24 +0100 Subject: Split HKTypeLambda from PolyType --- .../dotty/tools/dotc/core/TypeApplications.scala | 8 ++++---- .../src/dotty/tools/dotc/core/TypeComparer.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Types.scala | 5 +---- .../dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 6 +++--- .../src/dotty/tools/dotc/typer/Inferencing.scala | 4 ++-- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 24 +++++++++++----------- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 ++-- 9 files changed, 28 insertions(+), 31 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index eb3394082..1882489a5 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -75,7 +75,7 @@ object TypeApplications { } def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = tp match { - case tp @ PolyType/*###*/(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) + case tp @ HKTypeLambda(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) case _ => None } } @@ -253,7 +253,7 @@ class TypeApplications(val self: Type) extends AnyVal { def isHK(implicit ctx: Context): Boolean = self.dealias match { case self: TypeRef => self.info.isHK case self: RefinedType => false - case self: TypeLambda => true + case self: HKTypeLambda => true case self: SingletonType => false case self: TypeVar => // Using `origin` instead of `underlying`, as is done for typeParams, @@ -339,10 +339,10 @@ class TypeApplications(val self: Type) extends AnyVal { if (hkParams.isEmpty) self else { def adaptArg(arg: Type): Type = arg match { - case arg @ PolyType(tparams, body) if /*###*/ + case arg @ HKTypeLambda(tparams, body) if !tparams.corresponds(hkParams)(_.paramVariance == _.paramVariance) && tparams.corresponds(hkParams)(varianceConforms) => - PolyType(/*###*/ + HKTypeLambda( (tparams, hkParams).zipped.map((tparam, hkparam) => tparam.paramName.withVariance(hkparam.paramVariance)))( tl => arg.paramInfos.map(_.subst(arg, tl).bounds), diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 597b28088..131c31d6b 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -669,7 +669,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val tparams1 = tparams1a.drop(lengthDiff) variancesConform(tparams1, tparams) && { if (lengthDiff > 0) - tycon1b = PolyType(tparams1.map(_.paramName))(/*###*/ + tycon1b = HKTypeLambda(tparams1.map(_.paramName))( tl => tparams1.map(tparam => tl.integrate(tparams, tparam.paramInfo).bounds), tl => tycon1a.appliedTo(args1.take(lengthDiff) ++ tparams1.indices.toList.map(TypeParamRef(tl, _)))) @@ -1280,7 +1280,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { else if (tparams2.isEmpty) original(tp1.appliedTo(tp1.typeParams.map(_.paramInfoAsSeenFrom(tp1))), tp2) else - PolyType(/*###*/ + HKTypeLambda( paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2) .zipped.map((pname, tparam1, tparam2) => pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))( diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 4ba0a2924..d0c7990f8 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2762,7 +2762,7 @@ object Types { * type T[X] >: L <: U becomes type T >: ([X] -> L) <: ([X] -> U) */ override def fromParams[PI <: ParamInfo.Of[TypeName]](params: List[PI], resultType: Type)(implicit ctx: Context): Type = { - def expand(tp: Type) = PolyType.fromParams(params, tp) //### + def expand(tp: Type) = super.fromParams(params, tp) resultType match { case rt: TypeAlias => rt.derivedTypeAlias(expand(rt.alias)) @@ -2788,9 +2788,6 @@ object Types { def any(n: Int)(implicit ctx: Context) = apply(syntheticParamNames(n))( pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) - - override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName = - param.paramName.withVariance(param.paramVariance) //### } private object DepStatus { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index fc9d9c447..902d01c21 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -255,7 +255,7 @@ class TreePickler(pickler: TastyPickler) { pickleType(tpe.underlying) case tpe: HKTypeLambda => pickleMethodic(TYPELAMBDAtype, tpe) - case tpe: PolyType /*if richTypes*/ => //### + case tpe: PolyType if richTypes => pickleMethodic(POLYtype, tpe) case tpe: MethodType if richTypes => pickleMethodic(METHODtype, tpe) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 222d8af17..8d704f9a2 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -385,9 +385,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val apiTycon = simpleType(tycon) val apiArgs = args.map(processArg) new api.Parameterized(apiTycon, apiArgs.toArray) - case PolyType(tparams, res) => /*###*/ - val apiTparams = tparams.map(apiTypeParameter) - val apiRes = apiType(res) + case tl: TypeLambda => + val apiTparams = tl.typeParams.map(apiTypeParameter) + val apiRes = apiType(tl.resType) new api.Polymorphic(apiRes, apiTparams.toArray) case rt: RefinedType => val name = rt.refinedName.toString diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index 18a1982e1..48da9f35f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -119,9 +119,9 @@ object Inferencing { } } - /** If `tree` has a PolyType, infer its type parameters by comparing with expected type `pt` */ + /** If `tree` has a type lambda type, infer its type parameters by comparing with expected type `pt` */ def inferTypeParams(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree.tpe match { - case poly: PolyType => + case poly: TypeLambda => val (poly1, tvars) = constrained(poly, tree) val tree1 = tree.withType(poly1).appliedToTypeTrees(tvars) tree1.tpe <:< pt diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index a27175abd..ab342dc17 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -369,35 +369,35 @@ object ProtoTypes { /** A prototype for type constructors that are followed by a type application */ @sharable object AnyTypeConstructorProto extends UncachedGroundType with MatchAlways - /** Add all parameters in given polytype `pt` to the constraint's domain. + /** Add all parameters of given type lambda `tl` to the constraint's domain. * If the constraint contains already some of these parameters in its domain, - * make a copy of the polytype and add the copy's type parameters instead. - * Return either the original polytype, or the copy, if one was made. + * make a copy of the type lambda and add the copy's type parameters instead. + * Return either the original type lambda, or the copy, if one was made. * Also, if `owningTree` is non-empty, add a type variable for each parameter. - * @return The added polytype, and the list of created type variables. + * @return The added type lambda, and the list of created type variables. */ - def constrained(pt: PolyType, owningTree: untpd.Tree)(implicit ctx: Context): (PolyType, List[TypeTree]) = { + def constrained(tl: TypeLambda, owningTree: untpd.Tree)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = { val state = ctx.typerState assert(!(ctx.typerState.isCommittable && owningTree.isEmpty), s"inconsistent: no typevars were added to committable constraint ${state.constraint}") - def newTypeVars(pt: PolyType): List[TypeTree] = - for (n <- (0 until pt.paramNames.length).toList) + def newTypeVars(tl: TypeLambda): List[TypeTree] = + for (n <- (0 until tl.paramNames.length).toList) yield { val tt = new TypeTree().withPos(owningTree.pos) - tt.withType(new TypeVar(TypeParamRef(pt, n), state, tt, ctx.owner)) + tt.withType(new TypeVar(TypeParamRef(tl, n), state, tt, ctx.owner)) } val added = - if (state.constraint contains pt) pt.newLikeThis(pt.paramNames, pt.paramInfos, pt.resultType) - else pt + if (state.constraint contains tl) tl.newLikeThis(tl.paramNames, tl.paramInfos, tl.resultType) + else tl val tvars = if (owningTree.isEmpty) Nil else newTypeVars(added) ctx.typeComparer.addToConstraint(added, tvars.tpes.asInstanceOf[List[TypeVar]]) (added, tvars) } - /** Same as `constrained(pt, EmptyTree)`, but returns just the created polytype */ - def constrained(pt: PolyType)(implicit ctx: Context): PolyType = constrained(pt, EmptyTree)._1 + /** Same as `constrained(tl, EmptyTree)`, but returns just the created type lambda */ + def constrained(tl: TypeLambda)(implicit ctx: Context): TypeLambda = constrained(tl, EmptyTree)._1 /** Create a new TypeParamRef that represents a dependent method parameter singleton */ def newDepTypeParamRef(tp: Type)(implicit ctx: Context): TypeParamRef = { diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index fb1728578..2aa7036b4 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -329,7 +329,7 @@ trait TypeAssigner { def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context) = { val ownType = fn.tpe.widen match { - case pt: PolyType => + case pt: TypeLambda => val paramNames = pt.paramNames if (hasNamedArg(args)) { // Type arguments which are specified by name (immutable after this first loop) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 8bde5e4e3..9a9e45941 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1055,7 +1055,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit typr.println(s"adding refinement $refinement") checkRefinementNonCyclic(refinement, refineCls, seen) val rsym = refinement.symbol - if (rsym.info.isInstanceOf[PolyType] && rsym.allOverriddenSymbols.isEmpty) + if (rsym.info.isInstanceOf[TypeLambda] && rsym.allOverriddenSymbols.isEmpty) ctx.error(i"polymorphic refinement $rsym without matching type in parent $tpt1 is no longer allowed", refinement.pos) } assignType(cpy.RefinedTypeTree(tree)(tpt1, refinements1), tpt1, refinements1, refineCls) } @@ -1841,7 +1841,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match { - case _: MethodType | _: PolyType => + case _: MethodOrPoly => if (pt.args.lengthCompare(1) > 0 && isUnary(wtp) && ctx.canAutoTuple) adaptInterpolated(tree, pt.tupled, original) else -- cgit v1.2.3 From 15317555c94f613f266d7b0fb0a75b0b6ed2da6d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Mar 2017 12:42:55 +0100 Subject: Make PolyType a ground type It's too surprising to leave it as a type proxy. In all circumstances except erasure, it is not true that a PolyType is somehow the same as its result type. --- compiler/src/dotty/tools/dotc/core/TypeErasure.scala | 4 ++++ compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 8ff0be9d7..f35752644 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -389,6 +389,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean case rt => tp.derivedLambdaType(tp.paramNames, formals, rt) } + case tp: PolyType => + this(tp.resultType) case tp @ ClassInfo(pre, cls, classParents, decls, _) => if (cls is Package) tp else { @@ -517,6 +519,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean if (inst.exists) sigName(inst) else tpnme.Uninstantiated case tp: TypeProxy => sigName(tp.underlying) + case tp: PolyType => + sigName(tp.resultType) case _: ErrorType | WildcardType => tpnme.WILDCARD case tp: WildcardType => diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index d0c7990f8..1855e3376 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2706,7 +2706,7 @@ object Types { */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends HKLambda with TypeLambda { + extends MethodOrPoly with TypeLambda { type This = PolyType def companion = PolyType -- cgit v1.2.3 From 8d33ca7460493427055daaecca53c66127772831 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Mar 2017 12:44:27 +0100 Subject: Merge MethodType and PolyType functionality where possible Two benefits: (1) less code. (2) finding subtle bugs about parameter dependent method types. By merging with PolyTypes we are forced to take parameter dependencies into account. --- .../src/dotty/tools/dotc/core/Definitions.scala | 2 +- .../src/dotty/tools/dotc/core/Denotations.scala | 50 ++++++------------ compiler/src/dotty/tools/dotc/core/StdNames.scala | 6 --- .../src/dotty/tools/dotc/core/SymDenotations.scala | 3 +- .../src/dotty/tools/dotc/core/TypeComparer.scala | 60 ++++++++++----------- compiler/src/dotty/tools/dotc/core/Types.scala | 61 ++++++++-------------- .../dotty/tools/dotc/sbt/ExtractDependencies.scala | 4 +- .../src/dotty/tools/dotc/typer/Applications.scala | 3 +- .../src/dotty/tools/dotc/typer/Implicits.scala | 3 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +-- .../dotty/tools/dotc/typer/VarianceChecker.scala | 6 +-- .../src/dotty/tools/dotc/typer/Variances.scala | 4 +- 12 files changed, 78 insertions(+), 130 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 9360cabb1..b70fcb093 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -150,7 +150,7 @@ class Definitions { private def enterPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int, resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = { - val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount) + val tparamNames = PolyType.syntheticParamNames(typeParamCount) val tparamInfos = tparamNames map (_ => TypeBounds.empty) val ptype = PolyType(tparamNames)(_ => tparamInfos, resultTypeFn) enterMethod(cls, name, ptype, flags) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 7e552eda9..7341b96af 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -252,13 +252,12 @@ object Denotations { else throw new Error(s"cannot merge ${showType(tp1)} with ${showType(tp2)}") // flip condition for debugging } - /** Merge two lists of names. If names in corresponding positions match, keep them, + /** Merge parameter names of lambda types. If names in corresponding positions match, keep them, * otherwise generate new synthetic names. */ - def mergeNames[N <: Name](names1: List[N], names2: List[N], syntheticName: Int => N): List[N] = { - for ((name1, name2, idx) <- (names1, names2, 0 until names1.length).zipped) - yield if (name1 == name2) name1 else syntheticName(idx) - }.toList + private def mergeParamNames(tp1: LambdaType, tp2: LambdaType): List[tp1.ThisName] = + (for ((name1, name2, idx) <- (tp1.paramNames, tp2.paramNames, tp1.paramNames.indices).zipped) + yield if (name1 == name2) name1 else tp1.companion.syntheticParamName(idx)).toList /** Form a denotation by conjoining with denotation `that`. * @@ -308,27 +307,17 @@ object Denotations { case tp2: TypeBounds if tp2 contains tp1 => tp1 case _ => mergeConflict(tp1, tp2) } - case tp1: MethodType if isTerm => + case tp1: MethodOrPoly => tp2 match { - case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && - tp1.isImplicit == tp2.isImplicit => + case tp2: MethodOrPoly + if ctx.typeComparer.matchingParams(tp1, tp2) && + tp1.isImplicit == tp2.isImplicit => tp1.derivedLambdaType( - mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName), - tp1.paramInfos, + mergeParamNames(tp1, tp2), tp1.paramInfos, infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1))) case _ => mergeConflict(tp1, tp2) } - case tp1: PolyType if isTerm => - tp2 match { - case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) => - tp1.derivedLambdaType( - mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), - tp1.paramInfos, - infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1))) - case _: MethodicType => - mergeConflict(tp1, tp2) - } case _ => tp1 & tp2 } @@ -471,23 +460,14 @@ object Denotations { case tp2: TypeBounds if tp2 contains tp1 => tp2 case _ => mergeConflict(tp1, tp2) } - case tp1: MethodType => - tp2 match { - case tp2: MethodType - if ctx.typeComparer.matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && - tp1.isImplicit == tp2.isImplicit => - tp1.derivedLambdaType( - mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName), - tp1.paramInfos, tp1.resultType | tp2.resultType.subst(tp2, tp1)) - case _ => - mergeConflict(tp1, tp2) - } - case tp1: PolyType => + case tp1: MethodOrPoly => tp2 match { - case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) => + case tp2: MethodOrPoly + if ctx.typeComparer.matchingParams(tp1, tp2) && + tp1.isImplicit == tp2.isImplicit => tp1.derivedLambdaType( - mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), - tp1.paramInfos, tp1.resultType | tp2.resultType.subst(tp2, tp1)) + mergeParamNames(tp1, tp2), tp1.paramInfos, + tp1.resultType | tp2.resultType.subst(tp2, tp1)) case _ => mergeConflict(tp1, tp2) } diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 30fa03537..e7928fd09 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -722,9 +722,6 @@ object StdNames { case _ => termName("_" + j) } - def syntheticParamNames(num: Int): List[TermName] = - (0 until num).map(syntheticParamName)(breakOut) - def localDummyName(clazz: Symbol)(implicit ctx: Context): TermName = LOCALDUMMY_PREFIX ++ clazz.name ++ ">" @@ -747,9 +744,6 @@ object StdNames { def syntheticTypeParamName(i: Int): TypeName = "X" + i - def syntheticTypeParamNames(num: Int): List[TypeName] = - (0 until num).map(syntheticTypeParamName)(breakOut) - final val Conforms = encode("<:<") final val Uninstantiated: TypeName = "?$" diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 0ce61de95..56acbd9d6 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1146,8 +1146,7 @@ object SymDenotations { case tp: NamedType => hasSkolems(tp.prefix) case tp: RefinedType => hasSkolems(tp.parent) || hasSkolems(tp.refinedInfo) case tp: RecType => hasSkolems(tp.parent) - case tp: TypeLambda => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) - case tp: MethodType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) + case tp: LambdaType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) case tp: ExprType => hasSkolems(tp.resType) case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems) case tp: AndOrType => hasSkolems(tp.tp1) || hasSkolems(tp.tp2) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 131c31d6b..173520a10 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -428,9 +428,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { compareRec case tp2 @ HKApply(tycon2, args2) => compareHkApply2(tp1, tp2, tycon2, args2) - case tp2: TypeLambda => + case tp2: HKTypeLambda => def compareTypeLambda: Boolean = tp1.stripTypeVar match { - case tp1: TypeLambda if tp1.isInstanceOf[PolyType] == tp2.isInstanceOf[PolyType] => + case tp1: TypeLambda => /* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail * The issue is that, logically, bounds should compare contravariantly, * but that would invalidate a pattern exploited in t2994: @@ -484,12 +484,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case _ => } either(isSubType(tp1, tp21), isSubType(tp1, tp22)) || fourthTry(tp1, tp2) - case tp2: MethodType => + case tp2: MethodOrPoly => def compareMethod = tp1 match { - case tp1: MethodType => + case tp1: MethodOrPoly => (tp1.signature consistentParams tp2.signature) && - matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && - (tp1.isImplicit == tp2.isImplicit) && + matchingParams(tp1, tp2) && + tp1.isImplicit == tp2.isImplicit && isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1)) case _ => false @@ -1021,7 +1021,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { tp2.widen match { case tp2: MethodType => // implicitness is ignored when matching - matchingParams(tp1.paramInfos, tp2.paramInfos, tp1.isJava, tp2.isJava) && + matchingParams(tp1, tp2) && matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) case tp2 => relaxed && tp1.paramNames.isEmpty && @@ -1031,7 +1031,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { tp2.widen match { case tp2: PolyType => sameLength(tp1.paramNames, tp2.paramNames) && - matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) + matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) case _ => false } @@ -1047,28 +1047,28 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } } - /** Are `syms1` and `syms2` parameter lists with pairwise equivalent types? */ - def matchingParams(formals1: List[Type], formals2: List[Type], isJava1: Boolean, isJava2: Boolean): Boolean = formals1 match { - case formal1 :: rest1 => - formals2 match { - case formal2 :: rest2 => - (isSameTypeWhenFrozen(formal1, formal2) - || isJava1 && (formal2 isRef ObjectClass) && (formal1 isRef AnyClass) - || isJava2 && (formal1 isRef ObjectClass) && (formal2 isRef AnyClass)) && - matchingParams(rest1, rest2, isJava1, isJava2) - case nil => - false - } - case nil => - formals2.isEmpty - } - - /** Do generic types `poly1` and `poly2` have type parameters that - * have the same bounds (after renaming one set to the other)? + /** Do lambda types `lam1` and `lam2` have parameters that have the same types + * and the same implicit status? (after renaming one set to the other) */ - def matchingTypeParams(poly1: PolyType, poly2: PolyType): Boolean = - (poly1.paramInfos corresponds poly2.paramInfos)((b1, b2) => - isSameType(b1, b2.subst(poly2, poly1))) + def matchingParams(lam1: MethodOrPoly, lam2: MethodOrPoly): Boolean = { + /** Are `syms1` and `syms2` parameter lists with pairwise equivalent types? */ + def loop(formals1: List[Type], formals2: List[Type]): Boolean = formals1 match { + case formal1 :: rest1 => + formals2 match { + case formal2 :: rest2 => + val formal2a = if (lam2.isParamDependent) formal2.subst(lam2, lam1) else formal2 + (isSameTypeWhenFrozen(formal1, formal2a) + || lam1.isJava && (formal2 isRef ObjectClass) && (formal1 isRef AnyClass) + || lam2.isJava && (formal1 isRef ObjectClass) && (formal2 isRef AnyClass)) && + loop(rest1, rest2) + case nil => + false + } + case nil => + formals2.isEmpty + } + loop(lam1.paramInfos, lam2.paramInfos) + } // Type equality =:= @@ -1281,7 +1281,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { original(tp1.appliedTo(tp1.typeParams.map(_.paramInfoAsSeenFrom(tp1))), tp2) else HKTypeLambda( - paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2) + paramNames = (HKTypeLambda.syntheticParamNames(tparams1.length), tparams1, tparams2) .zipped.map((pname, tparam1, tparam2) => pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))( paramInfosExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 1855e3376..dd314c589 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -215,17 +215,15 @@ object Types { /** Is this the type of a method that has a repeated parameter type as * last parameter type? */ - def isVarArgsMethod(implicit ctx: Context): Boolean = this match { - case tp: PolyType => tp.resultType.isVarArgsMethod + def isVarArgsMethod(implicit ctx: Context): Boolean = stripPoly match { case mt: MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam case _ => false } /** Is this the type of a method with a leading empty parameter list? */ - def isNullaryMethod(implicit ctx: Context): Boolean = this match { + def isNullaryMethod(implicit ctx: Context): Boolean = stripPoly match { case MethodType(Nil) => true - case tp: PolyType => tp.resultType.isNullaryMethod case _ => false } @@ -2355,7 +2353,11 @@ object Types { override def resultType(implicit ctx: Context) = resType + def isJava: Boolean = false + def isImplicit = false + def isDependent(implicit ctx: Context): Boolean + def isParamDependent(implicit ctx: Context): Boolean final def isTermLambda = paramNames.head.isTermName final def isTypeLambda = paramNames.head.isTypeName @@ -2369,7 +2371,7 @@ object Types { if (isDependent) resultType.substParams(this, argTypes) else resultType - protected def companion: LambdaTypeCompanion[ThisName, PInfo, This] + def companion: LambdaTypeCompanion[ThisName, PInfo, This] /** The type `[tparams := paramRefs] tp`, where `tparams` can be * either a list of type parameter symbols or a list of lambda parameters @@ -2519,11 +2521,6 @@ object Types { type This = MethodType - protected def companion: MethodTypeCompanion - - def isJava = false - def isImplicit = false - val paramInfos = paramInfosExp(this) val resType = resultTypeExp(this) assert(resType.exists) @@ -2554,7 +2551,12 @@ object Types { } abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] { - def syntheticParamNames(n: Int): List[N] + def syntheticParamName(n: Int): N + + @sharable private val memoizedNames = new mutable.HashMap[Int, List[N]] + def syntheticParamNames(n: Int): List[N] = synchronized { + memoizedNames.getOrElseUpdate(n, (0 until n).map(syntheticParamName).toList) + } def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT def apply(paramNames: List[N], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT = @@ -2576,12 +2578,12 @@ object Types { abstract class TermLambdaCompanion[LT <: TermLambda] extends LambdaTypeCompanion[TermName, Type, LT] { - def syntheticParamNames(n: Int) = nme.syntheticParamNames(n) + def syntheticParamName(n: Int) = nme.syntheticParamName(n) } abstract class TypeLambdaCompanion[LT <: TypeLambda] extends LambdaTypeCompanion[TypeName, TypeBounds, LT] { - def syntheticParamNames(n: Int) = tpnme.syntheticTypeParamNames(n) + def syntheticParamName(n: Int) = tpnme.syntheticTypeParamName(n) } abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { @@ -2653,6 +2655,7 @@ object Types { type This <: TypeLambda def isDependent(implicit ctx: Context): Boolean = true + def isParamDependent(implicit ctx: Context): Boolean = true def newParamRef(n: Int) = TypeParamRef(this, n) @@ -3422,8 +3425,7 @@ object Types { object SAMType { def zeroParamClass(tp: Type)(implicit ctx: Context): Type = tp match { case tp: ClassInfo => - def zeroParams(tp: Type): Boolean = tp match { - case pt: PolyType => zeroParams(pt.resultType) + def zeroParams(tp: Type): Boolean = tp.stripPoly match { case mt: MethodType => mt.paramInfos.isEmpty && !mt.resultType.isInstanceOf[MethodType] case et: ExprType => true case _ => false @@ -3541,27 +3543,18 @@ object Types { variance = -variance derivedTypeBounds(tp, lo1, this(tp.hi)) - case tp: MethodType => - def mapOverMethod = { + case tp: LambdaType => + def mapOverLambda = { variance = -variance - val ptypes1 = tp.paramInfos mapConserve this + val ptypes1 = tp.paramInfos.mapConserve(this).asInstanceOf[List[tp.PInfo]] variance = -variance derivedLambdaType(tp)(ptypes1, this(tp.resultType)) } - mapOverMethod + mapOverLambda case tp: ExprType => derivedExprType(tp, this(tp.resultType)) - case tp: TypeLambda => - def mapOverPoly = { - variance = -variance - val bounds1 = tp.paramInfos.mapConserve(this).asInstanceOf[List[TypeBounds]] - variance = -variance - derivedLambdaType(tp)(bounds1, this(tp.resultType)) - } - mapOverPoly - case tp: RecType => derivedRecType(tp, this(tp.parent)) @@ -3769,7 +3762,7 @@ object Types { this(y, hi) } - case tp: MethodType => + case tp: LambdaType => variance = -variance val y = foldOver(x, tp.paramInfos) variance = -variance @@ -3778,12 +3771,6 @@ object Types { case ExprType(restpe) => this(x, restpe) - case tp: TypeLambda => - variance = -variance - val y = foldOver(x, tp.paramInfos) - variance = -variance - this(y, tp.resultType) - case tp: RecType => this(x, tp.parent) @@ -3884,9 +3871,7 @@ object Types { apply(x, tp.tref) case tp: ConstantType => apply(x, tp.underlying) - case tp: TermParamRef => - apply(x, tp.underlying) - case tp: TypeParamRef => + case tp: ParamRef => apply(x, tp.underlying) case _ => foldOver(x, tp) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 28ce9aa5a..0a061c841 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -256,9 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp traverse(tp.underlying) case tp: ConstantType => traverse(tp.underlying) - case tp: TermParamRef => - traverse(tp.underlying) - case tp: TypeParamRef => + case tp: ParamRef => traverse(tp.underlying) case _ => traverseChildren(tp) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 25c9c13d8..4e43e429b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1284,8 +1284,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case x => x } - def sizeFits(alt: TermRef, tp: Type): Boolean = tp match { - case tp: PolyType => sizeFits(alt, tp.resultType) + def sizeFits(alt: TermRef, tp: Type): Boolean = tp.stripPoly match { case tp: MethodType => val ptypes = tp.paramInfos val numParams = ptypes.length diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 703d2fc3c..6c0be51df 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -107,9 +107,8 @@ object Implicits { !(isFunctionInS2 || isImplicitConverter || isConforms) } - def discardForValueType(tpw: Type): Boolean = tpw match { + def discardForValueType(tpw: Type): Boolean = tpw.stripPoly match { case tpw: MethodType => !tpw.isImplicit - case tpw: PolyType => discardForValueType(tpw.resultType) case _ => false } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 9a9e45941..723e7007f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -748,7 +748,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case _ => } val ofFun = - if (nme.syntheticParamNames(args.length + 1) contains param.name) + if (MethodType.syntheticParamNames(args.length + 1) contains param.name) i" of expanded function $tree" else "" @@ -1285,9 +1285,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit * @param psym Its type symbol * @param cinfo The info of its constructor */ - def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo match { - case cinfo: PolyType => - maybeCall(ref, psym, cinfo.resultType) + def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo.stripPoly match { case cinfo @ MethodType(Nil) if cinfo.resultType.isInstanceOf[ImplicitMethodType] => val icall = New(ref).select(nme.CONSTRUCTOR).appliedToNone typedExpr(untpd.TypedSplice(icall))(superCtx) diff --git a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala index d5dd5a024..f88098519 100644 --- a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala +++ b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala @@ -88,10 +88,8 @@ class VarianceChecker()(implicit ctx: Context) { if (sym.variance != 0 && base.isContainedIn(sym.owner)) checkVarianceOfSymbol(sym) else if (sym.isAliasType) this(status, sym.info.bounds.hi) else foldOver(status, tp) - case tp: MethodType => - this(status, tp.resultType) // params will be checked in their TypeDef nodes. - case tp: PolyType => - this(status, tp.resultType) // params will be checked in their ValDef nodes. + case tp: MethodOrPoly => + this(status, tp.resultType) // params will be checked in their TypeDef or ValDef nodes. case AnnotatedType(_, annot) if annot.symbol == defn.UncheckedVarianceAnnot => status //case tp: ClassInfo => diff --git a/compiler/src/dotty/tools/dotc/typer/Variances.scala b/compiler/src/dotty/tools/dotc/typer/Variances.scala index 83ac23f7e..aeeef0275 100644 --- a/compiler/src/dotty/tools/dotc/typer/Variances.scala +++ b/compiler/src/dotty/tools/dotc/typer/Variances.scala @@ -79,7 +79,7 @@ object Variances { varianceInType(parent)(tparam) & varianceInType(rinfo)(tparam) case tp: RecType => varianceInType(tp.parent)(tparam) - case tp: MethodType => + case tp: MethodOrPoly => flip(varianceInTypes(tp.paramInfos)(tparam)) & varianceInType(tp.resultType)(tparam) case ExprType(restpe) => varianceInType(restpe)(tparam) @@ -94,8 +94,6 @@ object Variances { v } varianceInArgs(varianceInType(tycon)(tparam), args, tycon.typeParams) - case tp: PolyType => - flip(varianceInTypes(tp.paramInfos)(tparam)) & varianceInType(tp.resultType)(tparam) case AnnotatedType(tp, annot) => varianceInType(tp)(tparam) & varianceInAnnot(annot)(tparam) case tp: AndOrType => -- cgit v1.2.3 From 15e60e8637887892b0c03e5f6948f1222819a746 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Mar 2017 19:04:03 +0100 Subject: Narrow matches from TypeLambda to HKTypeLambda where appropriate --- compiler/src/dotty/tools/dotc/core/TypeApplications.scala | 6 ++++-- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 2 +- compiler/src/dotty/tools/dotc/core/Types.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/Inferencing.scala | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 1882489a5..23c3f96cc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -215,7 +215,7 @@ class TypeApplications(val self: Type) extends AnyVal { self match { case self: ClassInfo => self.cls.typeParams - case self: TypeLambda => + case self: HKTypeLambda => self.typeParams case self: TypeRef => val tsym = self.symbol @@ -386,7 +386,7 @@ class TypeApplications(val self: Type) extends AnyVal { val dealiased = stripped.safeDealias if (args.isEmpty || ctx.erasedTypes) self else dealiased match { - case dealiased: TypeLambda => + case dealiased: HKTypeLambda => def tryReduce = if (!args.exists(_.isInstanceOf[TypeBounds])) { val followAlias = Config.simplifyApplications && { @@ -414,6 +414,8 @@ class TypeApplications(val self: Type) extends AnyVal { else HKApply(dealiased, args) } tryReduce + case dealiased: PolyType => + dealiased.instantiate(args) case dealiased: AndOrType => dealiased.derivedAndOrType(dealiased.tp1.appliedTo(args), dealiased.tp2.appliedTo(args)) case dealiased: TypeAlias => diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 173520a10..da6d63387 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -430,7 +430,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { compareHkApply2(tp1, tp2, tycon2, args2) case tp2: HKTypeLambda => def compareTypeLambda: Boolean = tp1.stripTypeVar match { - case tp1: TypeLambda => + case tp1: HKTypeLambda => /* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail * The issue is that, logically, bounds should compare contravariantly, * but that would invalidate a pattern exploited in t2994: diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index dd314c589..fc6d5f44c 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -539,7 +539,7 @@ object Types { } def goApply(tp: HKApply) = tp.tycon match { - case tl: TypeLambda => + case tl: HKTypeLambda => go(tl.resType).mapInfo(info => tl.derivedLambdaAbstraction(tl.paramNames, tl.paramInfos, info).appliedTo(tp.args)) case _ => @@ -2830,7 +2830,7 @@ object Types { override def superType(implicit ctx: Context): Type = { if (ctx.period != validSuper) { cachedSuper = tycon match { - case tp: TypeLambda => defn.AnyType + case tp: HKTypeLambda => defn.AnyType case tp: TypeVar if !tp.inst.exists => // supertype not stable, since underlying might change return tp.underlying.applyIfParameterized(args) diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index 48da9f35f..632dbff76 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -121,9 +121,9 @@ object Inferencing { /** If `tree` has a type lambda type, infer its type parameters by comparing with expected type `pt` */ def inferTypeParams(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree.tpe match { - case poly: TypeLambda => - val (poly1, tvars) = constrained(poly, tree) - val tree1 = tree.withType(poly1).appliedToTypeTrees(tvars) + case tl: TypeLambda => + val (tl1, tvars) = constrained(tl, tree) + val tree1 = tree.withType(tl1).appliedToTypeTrees(tvars) tree1.tpe <:< pt fullyDefinedType(tree1.tpe, "template parent", tree.pos) tree1 -- cgit v1.2.3 From cdc91e28879a6882ce48f3a7fd7f0d7f432258b6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Mar 2017 19:07:41 +0100 Subject: Refactorings for efficiency - split LambdaType.equals into two equals so that tests are more specific (also avoids type testing against a trait) - re-order cases in some pattern matches with the aim to (1) move common cases earlier, (2) move more expensive trait type tests later. --- .../src/dotty/tools/dotc/core/SymDenotations.scala | 6 +- compiler/src/dotty/tools/dotc/core/Types.scala | 93 ++++++++++++---------- 2 files changed, 56 insertions(+), 43 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 56acbd9d6..602848a50 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1146,13 +1146,13 @@ object SymDenotations { case tp: NamedType => hasSkolems(tp.prefix) case tp: RefinedType => hasSkolems(tp.parent) || hasSkolems(tp.refinedInfo) case tp: RecType => hasSkolems(tp.parent) - case tp: LambdaType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) + case tp: TypeBounds => hasSkolems(tp.lo) || hasSkolems(tp.hi) + case tp: TypeVar => hasSkolems(tp.inst) case tp: ExprType => hasSkolems(tp.resType) case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems) + case tp: LambdaType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) case tp: AndOrType => hasSkolems(tp.tp1) || hasSkolems(tp.tp2) - case tp: TypeBounds => hasSkolems(tp.lo) || hasSkolems(tp.hi) case tp: AnnotatedType => hasSkolems(tp.tpe) - case tp: TypeVar => hasSkolems(tp.inst) case _ => false } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index fc6d5f44c..0a3191b84 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2393,8 +2393,18 @@ object Types { x => paramInfos.mapConserve(_.subst(this, x).asInstanceOf[PInfo]), x => resType.subst(this, x)) + protected def prefixString: String + final override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" + } + + abstract class HKLambda extends CachedProxyType with LambdaType { + final override def underlying(implicit ctx: Context) = resType + + final override def computeHash = doHash(paramNames, resType, paramInfos) + + // Defined here instead of in LambdaType for efficiency final override def equals(that: Any) = that match { - case that: LambdaType => + case that: HKLambda => this.paramNames == that.paramNames && this.paramInfos == that.paramInfos && this.resType == that.resType && @@ -2402,18 +2412,21 @@ object Types { case _ => false } - - protected def prefixString: String - final override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" - } - - abstract class HKLambda extends CachedProxyType with LambdaType { - final override def computeHash = doHash(paramNames, resType, paramInfos) - final override def underlying(implicit ctx: Context) = resType } abstract class MethodOrPoly extends CachedGroundType with LambdaType with TermType { final override def computeHash = doHash(paramNames, resType, paramInfos) + + // Defined here instead of in LambdaType for efficiency + final override def equals(that: Any) = that match { + case that: MethodOrPoly => + this.paramNames == that.paramNames && + this.paramInfos == that.paramInfos && + this.resType == that.resType && + (this.companion eq that.companion) + case _ => + false + } } trait TermLambda extends LambdaType { thisLambdaType => @@ -3543,6 +3556,26 @@ object Types { variance = -variance derivedTypeBounds(tp, lo1, this(tp.hi)) + case tp: RecType => + derivedRecType(tp, this(tp.parent)) + + case tp: TypeVar => + val inst = tp.instanceOpt + if (inst.exists) apply(inst) else tp + + case tp: HKApply => + def mapArg(arg: Type, tparam: ParamInfo): Type = { + val saved = variance + variance *= tparam.paramVariance + try this(arg) + finally variance = saved + } + derivedAppliedType(tp, this(tp.tycon), + tp.args.zipWithConserve(tp.typeParams)(mapArg)) + + case tp: ExprType => + derivedExprType(tp, this(tp.resultType)) + case tp: LambdaType => def mapOverLambda = { variance = -variance @@ -3552,12 +3585,6 @@ object Types { } mapOverLambda - case tp: ExprType => - derivedExprType(tp, this(tp.resultType)) - - case tp: RecType => - derivedRecType(tp, this(tp.parent)) - case tp @ SuperType(thistp, supertp) => derivedSuperType(tp, this(thistp), this(supertp)) @@ -3567,21 +3594,7 @@ object Types { case tp: ClassInfo => mapClassInfo(tp) - case tp: TypeVar => - val inst = tp.instanceOpt - if (inst.exists) apply(inst) else tp - - case tp: HKApply => - def mapArg(arg: Type, tparam: ParamInfo): Type = { - val saved = variance - variance *= tparam.paramVariance - try this(arg) - finally variance = saved - } - derivedAppliedType(tp, this(tp.tycon), - tp.args.zipWithConserve(tp.typeParams)(mapArg)) - - case tp: AndOrType => + case tp: AndOrType => derivedAndOrType(tp, this(tp.tp1), this(tp.tp2)) case tp: SkolemType => @@ -3762,17 +3775,14 @@ object Types { this(y, hi) } - case tp: LambdaType => - variance = -variance - val y = foldOver(x, tp.paramInfos) - variance = -variance - this(y, tp.resultType) + case tp: RecType => + this(x, tp.parent) case ExprType(restpe) => this(x, restpe) - case tp: RecType => - this(x, tp.parent) + case tp: TypeVar => + this(x, tp.underlying) case SuperType(thistp, supertp) => this(this(x, thistp), supertp) @@ -3797,6 +3807,12 @@ object Types { } foldArgs(this(x, tycon), tp.typeParams, args) + case tp: LambdaType => + variance = -variance + val y = foldOver(x, tp.paramInfos) + variance = -variance + this(y, tp.resultType) + case tp: AndOrType => this(this(x, tp.tp1), tp.tp2) @@ -3806,9 +3822,6 @@ object Types { case AnnotatedType(underlying, annot) => this(applyToAnnot(x, annot), underlying) - case tp: TypeVar => - this(x, tp.underlying) - case tp: WildcardType => this(x, tp.optBounds) -- cgit v1.2.3 From a15b14f22a66f5cfb3188abe5dbea2a12fc4ef4b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Mar 2017 21:34:56 +0100 Subject: Fix dotty-doc to take account of refactorings --- doc-tool/src/dotty/tools/dottydoc/model/factories.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala index 3e766a990..6b00934d2 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala @@ -79,7 +79,7 @@ object factories { case TypeBounds(lo, hi) => BoundsReference(expandTpe(lo), expandTpe(hi)) - case t: PolyParam => + case t: TypeParamRef => typeRef(t.paramName.show, params = params) case ExprType(tpe) => @@ -160,7 +160,7 @@ object factories { paramLists(pt.resultType) case mt: MethodType => - ParamListImpl(mt.paramNames.zip(mt.paramTypes).map { case (name, tpe) => + ParamListImpl(mt.paramNames.zip(mt.paramInfos).map { case (name, tpe) => NamedReference( name.decode.toString, returnType(tpe), @@ -169,13 +169,13 @@ object factories { ) }, mt.isImplicit) :: paramLists(mt.resultType) - case mp: MethodParam => + case mp: TermParamRef => paramLists(mp.underlying) case annot: AnnotatedType => paramLists(annot.tpe) - case (_: PolyParam | _: RefinedType | _: TypeRef | _: ThisType | + case (_: TypeParamRef | _: RefinedType | _: TypeRef | _: ThisType | _: ExprType | _: OrType | _: AndType | _: HKApply | _: TermRef | _: ConstantType) => Nil // return types should not be in the paramlist -- cgit v1.2.3 From 2e04574c4791428ed43f2fb98884361b2cd4e659 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Mar 2017 22:10:42 +0100 Subject: Generalize PolyType to TypeLambda in dotty-doc --- doc-tool/src/dotty/tools/dottydoc/model/factories.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala index 6b00934d2..03f11335e 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala @@ -106,7 +106,7 @@ object factories { case ci: ClassInfo => typeRef(ci.cls.name.show, query = ci.typeSymbol.showFullName) - case tl: PolyType => + case tl: TypeLambda => expandTpe(tl.resType) case OrType(left, right) => @@ -127,7 +127,7 @@ object factories { def typeParams(sym: Symbol)(implicit ctx: Context): List[String] = sym.info match { - case pt: PolyType => // TODO: not sure if this case is needed anymore + case pt: TypeLambda => // TODO: not sure if this case is needed anymore pt.paramNames.map(_.show.split("\\$").last) case ClassInfo(_, _, _, decls, _) => decls.iterator @@ -156,7 +156,7 @@ object factories { constructors(sym).head def paramLists(tpe: Type)(implicit ctx: Context): List[ParamList] = tpe match { - case pt: PolyType => + case pt: TypeLambda => paramLists(pt.resultType) case mt: MethodType => -- cgit v1.2.3 From d101f49223ca9b3cf807125fa42af581b729d9ce Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Mar 2017 23:00:31 +0100 Subject: Polishings --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 2 +- compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Symbols.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Types.scala | 11 ++++++----- compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 7 ------- compiler/src/dotty/tools/dotc/printing/Formatting.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 7 files changed, 13 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 6abcf6fff..66fc6bf84 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -245,7 +245,7 @@ object desugar { if (tdef.mods is PrivateLocalParam) { val tparam = cpy.TypeDef(tdef)(name = tdef.name.expandedName(ctx.owner)) .withMods(tdef.mods &~ PrivateLocal | ExpandedName) - val alias = cpy.TypeDef(tdef)(name = tdef.name, rhs = refOfDef(tparam)) + val alias = cpy.TypeDef(tdef)(rhs = refOfDef(tparam)) .withMods(tdef.mods & VarianceFlags | PrivateLocalParamAccessor | Synthetic) Thicket(tparam, alias) } diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 64621ec94..de96f644a 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -360,9 +360,9 @@ trait ConstraintHandling { if (comparedTypeLambdas.nonEmpty) { val approx = new ApproximatingTypeMap { def apply(t: Type): Type = t match { - case t @ TypeParamRef(pt: TypeLambda, n) if comparedTypeLambdas contains pt => + case t @ TypeParamRef(tl: TypeLambda, n) if comparedTypeLambdas contains tl => val effectiveVariance = if (fromBelow) -variance else variance - val bounds = pt.paramInfos(n) + val bounds = tl.paramInfos(n) if (effectiveVariance > 0) bounds.lo else if (effectiveVariance < 0) bounds.hi else NoType diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index a3c8e54b2..95ff1cb75 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -516,8 +516,8 @@ object Symbols { // ParamInfo types and methods def isTypeParam(implicit ctx: Context) = denot.is(TypeParam) def paramName(implicit ctx: Context) = name.asInstanceOf[ThisName] - def paramInfo(implicit ctx: Context) = denot.info.bounds - def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds + def paramInfo(implicit ctx: Context) = denot.info + def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this) def paramInfoOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter def paramVariance(implicit ctx: Context) = denot.variance def paramRef(implicit ctx: Context) = denot.typeRef diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 0a3191b84..0a23157c8 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -65,12 +65,13 @@ object Types { * | +- ExprType * | +- AnnotatedType * | +- TypeVar - * | +- HKLambda --------- PolyType + * | +- HKTypeLambda * | * +- GroundType -+- AndType * +- OrType - * +- MethodOrPoly ----- MethodType ---+- ImplicitMethodType - * | +- JavaMethodType + * +- MethodOrPoly ---+-- PolyType + * +-- MethodType ---+- ImplicitMethodType + * | +- JavaMethodType * +- ClassInfo * | * +- NoType @@ -2359,8 +2360,8 @@ object Types { def isDependent(implicit ctx: Context): Boolean def isParamDependent(implicit ctx: Context): Boolean - final def isTermLambda = paramNames.head.isTermName - final def isTypeLambda = paramNames.head.isTypeName + final def isTermLambda = isInstanceOf[TermLambda] + final def isTypeLambda = isInstanceOf[TypeLambda] final def isHigherKinded = isInstanceOf[TypeProxy] lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index b83045a11..4db995e10 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -227,13 +227,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle def readLengthType(): Type = { val end = readEnd() - def readNamesSkipParams: (List[Name], TreeReader) = { - val nameReader = fork - nameReader.skipTree() // skip result - val paramReader = nameReader.fork - (nameReader.readParamNames(end), paramReader) - } - def readMethodic[N <: Name, PInfo <: Type, LT <: LambdaType] (companion: LambdaTypeCompanion[N, PInfo, LT], nameMap: Name => N): LT = { val nameReader = fork diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index 4a57270a4..e8fa45403 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -31,7 +31,7 @@ object Formatting { case arg: Showable => try arg.show catch { - case NonFatal(ex) if false => s"[cannot display due to $ex, raw string = $toString]" + case NonFatal(ex) => s"[cannot display due to $ex, raw string = $toString]" } case _ => arg.toString } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 723e7007f..2760ceba9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1055,7 +1055,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit typr.println(s"adding refinement $refinement") checkRefinementNonCyclic(refinement, refineCls, seen) val rsym = refinement.symbol - if (rsym.info.isInstanceOf[TypeLambda] && rsym.allOverriddenSymbols.isEmpty) + if (rsym.info.isInstanceOf[PolyType] && rsym.allOverriddenSymbols.isEmpty) ctx.error(i"polymorphic refinement $rsym without matching type in parent $tpt1 is no longer allowed", refinement.pos) } assignType(cpy.RefinedTypeTree(tree)(tpt1, refinements1), tpt1, refinements1, refineCls) } -- cgit v1.2.3 From 4939b47bf3c2f74664e3976f23d82987ebf1ab43 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 20 Mar 2017 08:52:06 +0100 Subject: Update doc comment on HkTypeLambda/PolyType --- compiler/src/dotty/tools/dotc/core/Types.scala | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 0a23157c8..83fb70aa1 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2693,6 +2693,17 @@ object Types { } } + /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T` + * Variances are encoded in parameter names. A name starting with `+` + * designates a covariant parameter, a name starting with `-` designates + * a contravariant parameter, and every other name designates a non-variant parameter. + * + * @param paramNames The names `X_0`, ..., `X_n` + * @param paramInfosExp A function that, given the polytype itself, returns the + * parameter bounds `B_1`, ..., `B_n` + * @param resultTypeExp A function that, given the polytype itself, returns the + * result type `T`. + */ class HKTypeLambda(val paramNames: List[TypeName])( paramInfosExp: HKTypeLambda => List[TypeBounds], resultTypeExp: HKTypeLambda => Type) extends HKLambda with TypeLambda { @@ -2708,18 +2719,8 @@ object Types { protected def prefixString = "HKTypeLambda" } - /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T` - * This is used both as a type of a polymorphic method and as a type of - * a higher-kinded type parameter. Variances are encoded in parameter - * names. A name starting with `+` designates a covariant parameter, - * a name starting with `-` designates a contravariant parameter, - * and every other name designates a non-variant parameter. - * - * @param paramNames The names `X_0`, ..., `X_n` - * @param paramInfosExp A function that, given the polytype itself, returns the - * parameter bounds `B_1`, ..., `B_n` - * @param resultTypeExp A function that, given the polytype itself, returns the - * result type `T`. + /** The type of a polymorphic method. It has the same form as HKTypeLambda, + * except it applies to terms and parameters do not have variances. */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) -- cgit v1.2.3 From e800987c671c101a3643bfbaf93873db80ced9f3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Apr 2017 13:42:06 +0200 Subject: Adapt TastyPrinter to new format --- compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index fb37c9e7d..ce3722ff1 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -77,7 +77,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { printName(); printTree(); printTrees() case RETURN => printNat(); printTrees() - case METHODtype | POLYtype => + case METHODtype | POLYtype | TYPELAMBDAtype => printTree() until(end) { printName(); printTree() } case PARAMtype => -- cgit v1.2.3