diff options
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 24 | ||||
-rw-r--r-- | test/dotc/tests.scala | 1 | ||||
-rw-r--r-- | tests/neg/t1292.scala | 35 | ||||
-rw-r--r-- | tests/pos/t1292.scala (renamed from tests/pending/pos/t1292.scala) | 5 |
4 files changed, 60 insertions, 5 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index b6b17534e..967421f2b 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -121,7 +121,11 @@ object Types { * !!! Todo: What about non-final vals that contain abstract types? */ final def isLegalPrefix(implicit ctx: Context): Boolean = - isStable || memberNames(abstractTypeNameFilter).isEmpty + isStable || { + val absTypeNames = memberNames(abstractTypeNameFilter) + if (absTypeNames.nonEmpty) typr.println(s"abstract type members of ${this.showWithUnderlying}: $absTypeNames") + absTypeNames.isEmpty + } /** Is this type guaranteed not to have `null` as a value? * For the moment this is only true for modules, but it could @@ -811,6 +815,14 @@ object Types { /** Convert to text */ def toText(printer: Printer): Text = printer.toText(this) + /** Utility method to show the underlying type of a TypeProxy together + * with the proxy type itself. + */ + def showWithUnderlying(implicit ctx: Context): String = this match { + case tp: TypeProxy => s"$show with underlying ${tp.underlying.show}" + case _ => show + } + type VarianceMap = SimpleMap[TypeVar, Integer] /** All occurrences of type vars in this type that satisfy predicate @@ -2407,7 +2419,15 @@ object Types { /** A filter for names of abstract types of a given type */ object abstractTypeNameFilter extends NameFilter { def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = - name.isTypeName && ((pre member name).symbol is Deferred) + name.isTypeName && { + val mbr = pre.member(name) + (mbr.symbol is Deferred) && { + mbr.info match { + case TypeBounds(lo, hi) => lo ne hi + case _ => false + } + } + } } /** A filter for names of deferred term definitions of a given type */ diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index ee05dd15c..4b52b93c2 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -63,6 +63,7 @@ class tests extends CompilerTest { @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", "-language:noAutoTupling" :: Nil, xerrors = 3) @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 3) @Test def neg_t0654_polyalias = compileFile(negDir, "t0654", xerrors = 2) + @Test def neg_t1192_legalPrefix = compileFile(negDir, "t1192", xerrors = 1) @Test def dotc = compileDir(dotcDir + "tools/dotc", twice) @Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", twice) diff --git a/tests/neg/t1292.scala b/tests/neg/t1292.scala new file mode 100644 index 000000000..69e680320 --- /dev/null +++ b/tests/neg/t1292.scala @@ -0,0 +1,35 @@ +trait Foo[T <: Foo[T, Enum], Enum <: Enumeration] { + type StV = Enum#Value + type Meta = MegaFoo[T, Enum] + + type Slog <: Enumeration + + def getSingleton: Meta +} + +trait MegaFoo[T <: Foo[T, Enum], Enum <: Enumeration] extends Foo[T, Enum] { + def doSomething(what: T, misc: StV, dog: Meta#Event) = None + // error: Meta is not a valid prefix for '#'. + // The error is correct. Meta is not stable, and it has an abstract type member Slog + abstract class Event + object Event + + def stateEnumeration: Slog + def se2: Enum +} + +object E extends Enumeration { + val A = Value + val B = Value +} + +class RFoo extends Foo[RFoo, E.type] { + def getSingleton = MegaRFoo + + type Slog = E.type +} + +object MegaRFoo extends RFoo with MegaFoo[RFoo, E.type] { + def stateEnumeration = E + def se2 = E +} diff --git a/tests/pending/pos/t1292.scala b/tests/pos/t1292.scala index 83a996d53..8e69734e9 100644 --- a/tests/pending/pos/t1292.scala +++ b/tests/pos/t1292.scala @@ -2,13 +2,14 @@ trait Foo[T <: Foo[T, Enum], Enum <: Enumeration] { type StV = Enum#Value type Meta = MegaFoo[T, Enum] - type Slog <: Enumeration + type Slog = Enumeration def getSingleton: Meta } trait MegaFoo[T <: Foo[T, Enum], Enum <: Enumeration] extends Foo[T, Enum] { def doSomething(what: T, misc: StV, dog: Meta#Event) = None + abstract class Event object Event @@ -23,8 +24,6 @@ object E extends Enumeration { class RFoo extends Foo[RFoo, E.type] { def getSingleton = MegaRFoo - - type Slog = E.type } object MegaRFoo extends RFoo with MegaFoo[RFoo, E.type] { |