From 9421ff0f454a4daf7510e4be2cafa9e9244f8fbe Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 12 Apr 2019 12:18:58 +0200 Subject: [PATCH 1/5] Avoid printing typeargs of `new` twice --- .../src/dotty/tools/dotc/printing/RefinedPrinter.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 1056c8df4dca..40c7bd263a3e 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -254,7 +254,13 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = { val isQuote = tree.fun.hasType && tree.fun.symbol == defn.InternalQuoted_typeQuote val (open, close) = if (isQuote) (keywordStr("'["), keywordStr("]")) else ("[", "]") - toTextLocal(tree.fun).provided(!isQuote) ~ open ~ toTextGlobal(tree.args, ", ") ~ close + val funText = toTextLocal(tree.fun).provided(!isQuote) + tree.fun match { + case Select(New(tpt), nme.CONSTRUCTOR) if tpt.typeOpt.dealias.isInstanceOf[AppliedType] => + funText // type was already printed by toText(new) + case _ => + funText ~ open ~ toTextGlobal(tree.args, ", ") ~ close + } } protected def toTextCore[T >: Untyped](tree: Tree[T]): Text = { From e93f8abd6cc3fcd0435bfcbabd68f6689cb6df0f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 12 Apr 2019 23:30:20 +0200 Subject: [PATCH 2/5] Fix #6286: Fix ElimOpaque transformation SymTransformers used to transform only SymDenotations. But that does not work for ElimOpaque, where we also have to transform SingleDenotations that refer to opaque helpers. --- compiler/src/dotty/tools/dotc/ast/tpd.scala | 2 +- .../dotty/tools/dotc/core/DenotTransformers.scala | 5 ++++- .../dotty/tools/dotc/core/SymDenotations.scala | 11 +++-------- .../dotty/tools/dotc/transform/ElimOpaque.scala | 15 ++++----------- .../dotty/tools/dotc/transform/TypeUtils.scala | 12 ++++++++++++ tests/pos/i6286.scala | 6 ++++++ 6 files changed, 30 insertions(+), 21 deletions(-) create mode 100644 tests/pos/i6286.scala diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index c9d884ac673c..6a2faa74b13e 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -407,7 +407,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { ref(defn.DottyArraysModule).select(defn.newArrayMethod).withSpan(span) if (!ctx.erasedTypes) { - assert(!TypeErasure.isGeneric(elemTpe)) //needs to be done during typer. See Applications.convertNewGenericArray + assert(!TypeErasure.isGeneric(elemTpe), elemTpe) //needs to be done during typer. See Applications.convertNewGenericArray newArr.appliedToTypeTrees(TypeTree(returnTpe) :: Nil).appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(span) } else // after erasure newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(span) diff --git a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala index f8ea4fde1104..b6c47ac33af9 100644 --- a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -60,11 +60,14 @@ object DenotTransformers { /** A transformer that only transforms SymDenotations */ trait SymTransformer extends DenotTransformer { + /** Tramsform the info of a denotation that is not a Symdenotation */ + def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp + def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match { case ref: SymDenotation => transformSym(ref) - case _ => ref + case _ => ref.derivedSingleDenotation(ref.symbol, transformInfo(ref.info, ref.symbol)) } } diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index dae8aa99e997..6aaca2d587cc 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -19,6 +19,7 @@ import reporting.diagnostic.Message import reporting.diagnostic.messages.BadSymbolicReference import reporting.trace import collection.mutable +import transform.TypeUtils._ import scala.annotation.internal.sharable @@ -1082,16 +1083,10 @@ object SymDenotations { * containing object. */ def opaqueAlias(implicit ctx: Context): Type = { - if (isOpaqueHelper) { + if (isOpaqueHelper) owner.asClass.classInfo.selfType match { - case RefinedType(_, _, TypeBounds(lo, _)) => - def extractAlias(tp: Type): Type = tp match { - case OrType(alias, _) => alias - case tp: HKTypeLambda => tp.derivedLambdaType(resType = extractAlias(tp.resType)) - } - extractAlias(lo) + case RefinedType(_, _, bounds) => bounds.extractOpaqueAlias } - } else NoType } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala index 3d022d451833..013da087e586 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala @@ -2,25 +2,15 @@ package dotty.tools.dotc package transform import core._ -import Names._ import dotty.tools.dotc.transform.MegaPhase._ -import ast.Trees._ -import ast.untpd import Flags._ import Types._ -import Constants.Constant import Contexts.Context import Symbols._ import Decorators._ -import Annotations._ -import Annotations.ConcreteAnnotation -import Denotations.SingleDenotation import SymDenotations.SymDenotation -import scala.collection.mutable import DenotTransformers._ -import NameOps._ -import NameKinds.OuterSelectName -import StdNames._ +import TypeUtils._ object ElimOpaque { val name: String = "elimOpaque" @@ -37,6 +27,9 @@ class ElimOpaque extends MiniPhase with SymTransformer { // base types of opaque aliases change override def changesBaseTypes = true + override def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = + if (sym.isOpaqueHelper) TypeAlias(tp.extractOpaqueAlias) else tp + def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = if (sym.isOpaqueHelper) { sym.copySymDenotation( diff --git a/compiler/src/dotty/tools/dotc/transform/TypeUtils.scala b/compiler/src/dotty/tools/dotc/transform/TypeUtils.scala index a0adbfe7ba42..ee6938b78248 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeUtils.scala @@ -51,5 +51,17 @@ object TypeUtils { /** The `*:` equivalent of an instance of a Tuple class */ def toNestedPairs(implicit ctx: Context): Type = TypeOps.nestedPairs(tupleElementTypes) + + /** Extract opaque alias from TypeBounds type that combines it with the reference + * to the opaque type itself + */ + def extractOpaqueAlias(implicit ctx: Context): Type = self match { + case TypeBounds(lo, _) => + def extractAlias(tp: Type): Type = tp match { + case OrType(alias, _) => alias + case self: HKTypeLambda => self.derivedLambdaType(resType = extractAlias(self.resType)) + } + extractAlias(lo) + } } } diff --git a/tests/pos/i6286.scala b/tests/pos/i6286.scala new file mode 100644 index 000000000000..bfd20f99f94e --- /dev/null +++ b/tests/pos/i6286.scala @@ -0,0 +1,6 @@ +object A { + opaque type T33 = Int + object T33 { + val a = new Array[T33](3) + } +} \ No newline at end of file From 0fadbe316d50096e533e030ef6a27505ab8705cf Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 13 Apr 2019 09:50:38 +0200 Subject: [PATCH 3/5] transformInfo -> transformNonSymInfo --- compiler/src/dotty/tools/dotc/core/DenotTransformers.scala | 4 ++-- compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala index b6c47ac33af9..6ad288f700cc 100644 --- a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -61,13 +61,13 @@ object DenotTransformers { trait SymTransformer extends DenotTransformer { /** Tramsform the info of a denotation that is not a Symdenotation */ - def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp + def transformNonSymInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match { case ref: SymDenotation => transformSym(ref) - case _ => ref.derivedSingleDenotation(ref.symbol, transformInfo(ref.info, ref.symbol)) + case _ => ref.derivedSingleDenotation(ref.symbol, transformNonSymInfo(ref.info, ref.symbol)) } } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala index 013da087e586..9d78a35431bf 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala @@ -27,7 +27,7 @@ class ElimOpaque extends MiniPhase with SymTransformer { // base types of opaque aliases change override def changesBaseTypes = true - override def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = + override def transformNonSymInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = if (sym.isOpaqueHelper) TypeAlias(tp.extractOpaqueAlias) else tp def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = From 1c5b8a4aab5a6d3ec7794c184559cb6d1c39cfbe Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 13 Apr 2019 10:39:10 +0200 Subject: [PATCH 4/5] Make ElimOpaque a DenotTransformer --- .../tools/dotc/core/DenotTransformers.scala | 11 +++++----- .../tools/dotc/transform/ElimOpaque.scala | 22 ++++++++++--------- .../dotty/tools/dotc/transform/Getters.scala | 4 ++++ 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala index 6ad288f700cc..8b3bca405488 100644 --- a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -57,17 +57,18 @@ object DenotTransformers { protected def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = true } - /** A transformer that only transforms SymDenotations */ + /** A transformer that only transforms SymDenotations. + * Note: Infos of non-sym denotations are left as is. So the transformer should + * be used before erasure only if this is not a problem. After erasure, all + * denotations are SymDenotations, so SymTransformers can be used freely. + */ trait SymTransformer extends DenotTransformer { - /** Tramsform the info of a denotation that is not a Symdenotation */ - def transformNonSymInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp - def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match { case ref: SymDenotation => transformSym(ref) - case _ => ref.derivedSingleDenotation(ref.symbol, transformNonSymInfo(ref.info, ref.symbol)) + case _ => ref } } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala index 9d78a35431bf..c9f5d829a148 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala @@ -8,6 +8,7 @@ import Types._ import Contexts.Context import Symbols._ import Decorators._ +import Denotations.SingleDenotation import SymDenotations.SymDenotation import DenotTransformers._ import TypeUtils._ @@ -17,7 +18,7 @@ object ElimOpaque { } /** Rewrites opaque type aliases to normal alias types */ -class ElimOpaque extends MiniPhase with SymTransformer { +class ElimOpaque extends MiniPhase with DenotTransformer { override def phaseName: String = ElimOpaque.name @@ -27,14 +28,15 @@ class ElimOpaque extends MiniPhase with SymTransformer { // base types of opaque aliases change override def changesBaseTypes = true - override def transformNonSymInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = - if (sym.isOpaqueHelper) TypeAlias(tp.extractOpaqueAlias) else tp - - def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = - if (sym.isOpaqueHelper) { - sym.copySymDenotation( - info = TypeAlias(sym.opaqueAlias), - initFlags = sym.flags &~ (Opaque | Deferred)) + def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = + if (ref.symbol.isOpaqueHelper) + ref match { + case sym: SymDenotation => + sym.copySymDenotation( + info = TypeAlias(sym.opaqueAlias), + initFlags = sym.flags &~ (Opaque | Deferred)) + case _ => + ref.derivedSingleDenotation(ref.symbol, TypeAlias(ref.info.extractOpaqueAlias)) } - else sym + else ref } \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/transform/Getters.scala b/compiler/src/dotty/tools/dotc/transform/Getters.scala index d6d16a72ad47..f635412fae23 100644 --- a/compiler/src/dotty/tools/dotc/transform/Getters.scala +++ b/compiler/src/dotty/tools/dotc/transform/Getters.scala @@ -65,6 +65,10 @@ class Getters extends MiniPhase with SymTransformer { d.copySymDenotation( initFlags = d.flags | maybeStable | AccessorCreationFlags, info = ExprType(d.info)) + // Note: This change will only affect the SymDenotation itself, not + // SingleDenotations referring to a getter. In this case it does not + // seem to be a problem since references to a getter don't care whether + // it's a `T` or a `=> T` } else d From efc48c3256038c8b5bcbdb7ec958ce1616eb0059 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 13 Apr 2019 15:00:33 +0200 Subject: [PATCH 5/5] Fix #6287: Reset opaque companions in ElimOpaque --- .../tools/dotc/transform/ElimOpaque.scala | 26 ++++++++++++------- tests/pos/i6287.scala | 13 ++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 tests/pos/i6287.scala diff --git a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala index c9f5d829a148..e4536c054fb1 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala @@ -28,15 +28,21 @@ class ElimOpaque extends MiniPhase with DenotTransformer { // base types of opaque aliases change override def changesBaseTypes = true - def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = - if (ref.symbol.isOpaqueHelper) - ref match { - case sym: SymDenotation => - sym.copySymDenotation( - info = TypeAlias(sym.opaqueAlias), - initFlags = sym.flags &~ (Opaque | Deferred)) - case _ => - ref.derivedSingleDenotation(ref.symbol, TypeAlias(ref.info.extractOpaqueAlias)) + def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = { + val sym = ref.symbol + ref match { + case ref: SymDenotation if sym.isOpaqueHelper => + ref.copySymDenotation( + info = TypeAlias(ref.opaqueAlias), + initFlags = ref.flags &~ (Opaque | Deferred)) + case ref: SymDenotation if sym.isOpaqueCompanion => + val ref1 = ref.copySymDenotation(initFlags = ref.flags &~ Opaque) + ref1.registeredCompanion = NoSymbol + ref1 + case _ if sym.isOpaqueHelper => + ref.derivedSingleDenotation(sym, TypeAlias(ref.info.extractOpaqueAlias)) + case _ => + ref } - else ref + } } \ No newline at end of file diff --git a/tests/pos/i6287.scala b/tests/pos/i6287.scala new file mode 100644 index 000000000000..c9c6f8fca97f --- /dev/null +++ b/tests/pos/i6287.scala @@ -0,0 +1,13 @@ +object O{ + def m() = { + opaque type T = Int + object T + } +} +object A { + { + opaque type T = Int + object T + println + } +} \ No newline at end of file