diff options
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 7 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 29 |
3 files changed, 15 insertions, 23 deletions
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index e17b655f9..8393eb56f 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -304,8 +304,6 @@ object StdNames { val ArrayAnnotArg: N = "ArrayAnnotArg" val Constant: N = "Constant" val ConstantType: N = "ConstantType" - val DummyHi: N = "DummyHi" - val DummyLo: N = "DummyLo" val ExistentialTypeTree: N = "ExistentialTypeTree" val Flag : N = "Flag" val Ident: N = "Ident" diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 33d108540..feee05d86 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -104,9 +104,10 @@ object Types { */ def isRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match { case this1: TypeRef => - val thissym = this1.symbol - if (thissym.isAliasType) this1.info.bounds.hi.isRef(sym) - else thissym eq sym + this1.info match { // see comment in Namers/typeDefSig + case TypeBounds(lo, hi) if lo eq hi => hi.isRef(sym) + case _ => this1.symbol eq sym + } case this1: RefinedType => // make sure all refinements are type arguments this1.parent.isRef(sym) && this.argInfos.nonEmpty diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 7490e88e9..86376356c 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -673,7 +673,17 @@ class Namer { typer: Typer => def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = { completeParams(tdef.tparams) - setDummyInfo(sym) + sym.info = TypeBounds.empty + // Temporarily set info of defined type T to ` >: Nothing <: Any. + // This is done to avoid cyclic reference errors for F-bounds. + // This is subtle: `sym` has now an empty TypeBounds, but is not automatically + // made an abstract type. If it had been made an abstract type, it would count as an + // abstract type of its enclosing class, which might make that class an invalid + // prefix. I verified this would lead to an error when compiling io.ClassPath. + // A distilled version is in pos/prefix.scala. + // + // The scheme critically relies on an implementation detail of isRef, which + // inspects a TypeRef's info, instead of simply dealiasing alias types. val tparamSyms = tdef.tparams map symbolOfTree val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree] val toParameterize = tparamSyms.nonEmpty && !isDerived @@ -690,21 +700,4 @@ class Namer { typer: Typer => sym.info = NoCompleter checkNonCyclic(sym, unsafeInfo, reportErrors = true) } - - /** Temporarily set info of defined type T to - * - * T >: dummyLo <: dummyHi - * type dummyLo, dummyHi - * - * This is done to avoid cyclic reference errors for F-bounds. - * The type is intentionally chosen so that it cannot possibly be - * elided when taking a union or intersection. - */ - private def setDummyInfo(sym: Symbol)(implicit ctx: Context): Unit = { - def dummyBound(name: TypeName) = - ctx.newSymbol(sym.owner, name, Synthetic | Deferred, TypeBounds.empty) - val dummyLo = dummyBound(tpnme.DummyLo) - val dummyHi = dummyBound(tpnme.DummyHi) - sym.info = TypeBounds(TypeRef(NoPrefix, dummyLo), TypeRef(NoPrefix, dummyHi)) - } }
\ No newline at end of file |