aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Checking.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-03-12 14:12:17 +0100
committerMartin Odersky <odersky@gmail.com>2016-03-12 14:14:29 +0100
commit216c195f5592e3f4cbf96ed00b3710a46307cd8a (patch)
treeef4a6ba8bdb8d06e00bb1c34b470eb5f196d3272 /src/dotty/tools/dotc/typer/Checking.scala
parente68d68414fa346fad9dee204746d826ee172e861 (diff)
downloaddotty-216c195f5592e3f4cbf96ed00b3710a46307cd8a.tar.gz
dotty-216c195f5592e3f4cbf96ed00b3710a46307cd8a.tar.bz2
dotty-216c195f5592e3f4cbf96ed00b3710a46307cd8a.zip
Have checkNotPrivate skip over private aliases.
CheckNotPrivate now avoids private aliases, so that types sat prepresentable in transformation phases. This does not solve the problem that private classes or abstract types might leak coming from Scala 2, but there is not really a good cure for that. We can reject them outright or allow them under language:Scala2 and hope for the best.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Checking.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala55
1 files changed, 34 insertions, 21 deletions
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 0ca121925..9b1f756b7 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -327,40 +327,53 @@ object Checking {
* to a private type or value which is invisible at a point where `M` is still
* visible. As an exception, we allow references to type aliases if the underlying
* type of the alias is not a leak. So type aliases are transparent as far as
- * leak testing is concerned. See 997.scala for tests.
+ * leak testing is concerned.
+ * @return The `info` of `sym`, with problematic aliases expanded away.
+ * See i997.scala for tests, i1130.scala for a case where it matters that we
+ * transform leaky aliases away.
*/
- def checkNoPrivateLeaks(tree: MemberDef)(implicit ctx: Context): Unit = {
- type Errors = List[(String, Position)]
- val sym = tree.symbol
- val notPrivate = new TypeAccumulator[Errors] {
+ def checkNoPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = {
+ class NotPrivate extends TypeMap {
+ type Errors = List[(String, Position)]
+ var errors: Errors = Nil
def accessBoundary(sym: Symbol): Symbol =
if (sym.is(Private)) sym.owner
else if (sym.privateWithin.exists) sym.privateWithin
else if (sym.is(Package)) sym
else accessBoundary(sym.owner)
- def apply(errors: Errors, tp: Type): Errors = tp match {
+ def apply(tp: Type): Type = tp match {
case tp: NamedType =>
- val errors1 =
+ val prevErrors = errors
+ var tp1 =
if (tp.symbol.is(Private) &&
- !accessBoundary(sym).isContainedIn(tp.symbol.owner)) {
- (d"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}", tree.pos) :: errors
- } else foldOver(errors, tp)
- if ((errors1 ne errors) && tp.info.isAlias) {
+ !accessBoundary(sym).isContainedIn(tp.symbol.owner)) {
+ errors = (d"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}",
+ pos) :: errors
+ tp
+ }
+ else mapOver(tp)
+ if ((errors ne prevErrors) && tp.info.isAlias) {
// try to dealias to avoid a leak error
- val errors2 = apply(errors, tp.info.bounds.hi)
- if (errors2 eq errors) errors2
- else errors1
- } else errors1
+ val savedErrors = errors
+ errors = prevErrors
+ val tp2 = apply(tp.info.bounds.hi)
+ if (errors eq prevErrors) tp1 = tp2
+ else errors = savedErrors
+ }
+ tp1
case tp: ClassInfo =>
- (apply(errors, tp.prefix) /: tp.parentsWithArgs)(apply)
+ tp.derivedClassInfo(
+ prefix = apply(tp.prefix),
+ classParents = tp.parentsWithArgs.map(p =>
+ apply(p).underlyingClassRef(refinementOK = false).asInstanceOf[TypeRef]))
case _ =>
- foldOver(errors, tp)
+ mapOver(tp)
}
}
- if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
- val errors = notPrivate(Nil, sym.info)
- errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) }
- }
+ val notPrivate = new NotPrivate
+ val info = notPrivate(sym.info)
+ notPrivate.errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) }
+ info
}
}