From c4aa3c058904912ba1b5696b2aaa4d9234dc5c79 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 12 Nov 2014 17:12:44 +0100 Subject: Avoid forcing infos of some symbols in InfoTransforms Provides the "mayChange" hook to exclude symbols from being completed prior to a transformInfo. --- src/dotty/tools/dotc/core/DenotTransformers.scala | 20 +++++++++++++++----- src/dotty/tools/dotc/transform/ElimByName.scala | 2 ++ src/dotty/tools/dotc/transform/ElimRepeated.scala | 2 ++ src/dotty/tools/dotc/transform/ExplicitOuter.scala | 2 ++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/dotty/tools/dotc/core/DenotTransformers.scala b/src/dotty/tools/dotc/core/DenotTransformers.scala index 0e31d87e6..02d27ea33 100644 --- a/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -38,13 +38,23 @@ object DenotTransformers { def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = { - val info1 = transformInfo(ref.info, ref.symbol) - if (info1 eq ref.info) ref - else ref match { - case ref: SymDenotation => ref.copySymDenotation(info = info1) - case _ => ref.derivedSingleDenotation(ref.symbol, info1) + val sym = ref.symbol + if (sym.exists && !mayChange(sym)) ref + else { + val info1 = transformInfo(ref.info, ref.symbol) + if (info1 eq ref.info) ref + else ref match { + case ref: SymDenotation => ref.copySymDenotation(info = info1) + case _ => ref.derivedSingleDenotation(ref.symbol, info1) + } } } + + /** Denotations with a symbol where `mayChange` is false are guaranteed to be + * unaffected by this transform, so `transformInfo` need not be run. This + * can save time, and more importantly, can help avoid forcing symbol completers. + */ + protected def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = true } /** A transformer that only transforms SymDenotations */ diff --git a/src/dotty/tools/dotc/transform/ElimByName.scala b/src/dotty/tools/dotc/transform/ElimByName.scala index 40fd48327..7adee3a8a 100644 --- a/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/src/dotty/tools/dotc/transform/ElimByName.scala @@ -116,4 +116,6 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform case ExprType(rt) if exprBecomesFunction(sym) => defn.FunctionType(Nil, rt) case _ => tp } + + override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym.isTerm } diff --git a/src/dotty/tools/dotc/transform/ElimRepeated.scala b/src/dotty/tools/dotc/transform/ElimRepeated.scala index eb44c3e2c..03fd28a26 100644 --- a/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -28,6 +28,8 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransfo def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = elimRepeated(tp) + override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym is Method + private def elimRepeated(tp: Type)(implicit ctx: Context): Type = tp.stripTypeVar match { case tp @ MethodType(paramNames, paramTypes) => val resultType1 = elimRepeated(tp.resultType) diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 436d9bcf7..0810f7d9c 100644 --- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -55,6 +55,8 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf tp } + override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym.isClass + /** First, add outer accessors if a class does not have them yet and it references an outer this. * If the class has outer accessors, implement them. * Furthermore, if a parent trait might have an outer accessor, -- cgit v1.2.3