From 38ac02916ec0beef0cb93f0fdd48ad1f9dfdcf48 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 20 Jul 2015 13:59:34 +0200 Subject: Replace isLambda with ifHK Replace occurrences of isLambda with isHK, because isHK is a bit faster and simplier. --- src/dotty/tools/dotc/core/TypeApplications.scala | 55 +++++++----------------- src/dotty/tools/dotc/core/TypeComparer.scala | 7 ++- 2 files changed, 18 insertions(+), 44 deletions(-) (limited to 'src/dotty/tools/dotc/core') diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 75a0b9957..66542d02d 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -141,13 +141,11 @@ class TypeApplications(val self: Type) extends AnyVal { def isInstantiatedLambda(implicit ctx: Context): Boolean = isSafeLambda && typeParams.isEmpty + /** Is receiver type higher-kinded (i.e. of kind != "*")? */ def isHK(implicit ctx: Context): Boolean = self.dealias match { - case self: TypeRef => - self.info match { - case TypeBounds(_, hi) => hi.isHK - case _ => false - } + case self: TypeRef => self.info.isHK case RefinedType(_, name) => name == tpnme.hkApply || name.isLambdaArgName + case TypeBounds(_, hi) => hi.isHK case _ => false } @@ -160,24 +158,7 @@ class TypeApplications(val self: Type) extends AnyVal { println(s"precomplete decls = ${self.typeSymbol.unforcedDecls.toList.map(_.denot).mkString("\n ")}") } val tparam = tparams.head - val needsEtaExpand = - try { - (tparam is HigherKinded) && !arg.isLambda && arg.typeParams.nonEmpty - } - catch { - case ex: CyclicReference => - if (ctx.mode.is(Mode.Scala2Unpickling)) - // When unpickling Scala2, we might run into cyclic references when - // checking whether eta expansion is needed or eta expanding. - // (e.g. try compile collection/generic/GenericTraversableTemplate.scala). - // In that case, back out gracefully. Ideally, we should not have - // underdefined pickling data that requires post-transformations like - // eta expansion, but we can't change Scala2's. - false - else throw ex - } - val arg1 = if (needsEtaExpand) arg.EtaExpand else arg - val tp1 = RefinedType(tp, tparam.name, arg1.toBounds(tparam)) + val tp1 = RefinedType(tp, tparam.name, arg.toBounds(tparam)) matchParams(tp1, tparams.tail, args1) case nil => tp } @@ -216,29 +197,23 @@ class TypeApplications(val self: Type) extends AnyVal { tp } - def isHK(tp: Type): Boolean = tp match { + /** Same as isHK, except we classify all abstract types as HK, + * (they must be, because the are applied). This avoids some forcing and + * CyclicReference errors of the standard isHK. + */ + def isKnownHK(tp: Type): Boolean = tp match { case tp: TypeRef => val sym = tp.symbol if (sym.isClass) sym.isLambdaTrait - else !sym.isAliasType || isHK(tp.info) - case tp: TypeProxy => isHK(tp.underlying) + else !sym.isAliasType || isKnownHK(tp.info) + case tp: TypeProxy => isKnownHK(tp.underlying) case _ => false } if (args.isEmpty || ctx.erasedTypes) self else { val res = instantiate(self, self) - if (isHK(res)) - // Note: isHK needs to be conservative, using isSafeLambda - // in order to avoid cyclic reference errors. But this means that some fully - // instantiated types will remain unprojected, which essentially means - // that they stay as higher-kinded types. checkNonCyclic checks the type again - // and potentially inserts an #Apply then. Hopefully, this catches all types - // that fall through the hole. Not adding an #Apply typically manifests itself - // with a <:< failure of two types that "look the same". An example is #779, - // where compiling scala.immutable.Map gives a bounds violation. - TypeRef(res, tpnme.hkApply) - else res + if (isKnownHK(res)) TypeRef(res, tpnme.hkApply) else res } } @@ -510,9 +485,9 @@ class TypeApplications(val self: Type) extends AnyVal { //.ensuring(res => res.EtaReduce =:= self, s"res = $res, core = ${res.EtaReduce}, self = $self, hc = ${res.hashCode}") } - /** Eta expand if `bound` is a type lambda */ - def EtaExpandIfLambda(bound: Type)(implicit ctx: Context): Type = - if (bound.isLambda && self.typeSymbol.isClass && typeParams.nonEmpty && !isLambda) EtaExpand + /** Eta expand if `bound` is a higher-kinded type */ + def EtaExpandIfHK(bound: Type)(implicit ctx: Context): Type = + if (bound.isHK && !isHK && self.typeSymbol.isClass && typeParams.nonEmpty) EtaExpand else self /** If `self` is an eta expansion of type T, return T, otherwise NoType */ diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index a8598ae44..35e4d804b 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -633,11 +633,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Does `tp` need to be eta lifted to be comparable to `target`? */ private def needsEtaLift(tp: Type, target: RefinedType): Boolean = { - //default.echo(i"needs eta $tp $target?", { // @@@ rewrite + // if (tp.isLambda != tp.isHK) println(i"discrepancy for $tp, isLambda = ${tp.isLambda}, isHK = ${tp.isHK}") val name = target.refinedName - (name.isLambdaArgName || (name eq tpnme.hkApply)) && target.isLambda && - tp.exists && !tp.isLambda - //}) + (name.isLambdaArgName || (name eq tpnme.hkApply)) && + tp.exists && !tp.isLambda // we do encounter Lambda classes without any arguments here @@@ check whether this makes sense. } /** Narrow gadt.bounds for the type parameter referenced by `tr` to include -- cgit v1.2.3