aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala2
3 files changed, 8 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 89facfee5..827e851a9 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -117,14 +117,15 @@ object Types {
}
/** A type T is a legal prefix in a type selection T#A if
- * T is stable or T contains no abstract types
+ * T is stable or T contains no abstract types except possibly A.
* !!! Todo: What about non-final vals that contain abstract types?
*/
- final def isLegalPrefix(implicit ctx: Context): Boolean =
+ final def isLegalPrefixFor(selector: Name)(implicit ctx: Context): Boolean =
isStable || {
val absTypeNames = memberNames(abstractTypeNameFilter)
if (absTypeNames.nonEmpty) typr.println(s"abstract type members of ${this.showWithUnderlying()}: $absTypeNames")
- absTypeNames.isEmpty
+ absTypeNames.isEmpty ||
+ absTypeNames.head == selector && absTypeNames.tail.isEmpty
}
/** Is this type guaranteed not to have `null` as a value?
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 5e52c5d7e..7da00e051 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -51,8 +51,8 @@ trait Checking {
/** Check that type `tp` is a legal prefix for '#'.
* @return The type itself
*/
- def checkLegalPrefix(tp: Type, pos: Position)(implicit ctx: Context): Unit =
- if (!tp.isLegalPrefix) ctx.error(d"$tp is not a valid prefix for '#'", pos)
+ def checkLegalPrefix(tp: Type, selector: Name, pos: Position)(implicit ctx: Context): Unit =
+ if (!tp.isLegalPrefixFor(selector)) ctx.error(d"$tp is not a valid prefix for '# $selector'", pos)
/** Check that `tp` is a class type with a stable prefix. Also, if `isFirst` is
* false check that `tp` is a trait.
@@ -139,7 +139,7 @@ trait NoChecking extends Checking {
override def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = tree
override def checkBounds(args: List[tpd.Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit = ()
override def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = ()
- override def checkLegalPrefix(tp: Type, pos: Position)(implicit ctx: Context): Unit = ()
+ override def checkLegalPrefix(tp: Type, selector: Name, pos: Position)(implicit ctx: Context): Unit = ()
override def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type = tp
override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = ()
override def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index d6b724270..c01cf714f 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -277,7 +277,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context): SelectFromTypeTree = track("typedSelectFromTypeTree") {
val qual1 = typedType(tree.qualifier, selectionProto(tree.name, pt, this))
- checkLegalPrefix(qual1.tpe, qual1.pos)
+ checkLegalPrefix(qual1.tpe, tree.name, qual1.pos)
assignType(cpy.SelectFromTypeTree(tree, qual1, tree.name), qual1)
}