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