diff options
author | Martin Odersky <odersky@gmail.com> | 2016-03-12 14:12:17 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-03-12 14:14:29 +0100 |
commit | 216c195f5592e3f4cbf96ed00b3710a46307cd8a (patch) | |
tree | ef4a6ba8bdb8d06e00bb1c34b470eb5f196d3272 /src/dotty/tools/dotc/typer/Checking.scala | |
parent | e68d68414fa346fad9dee204746d826ee172e861 (diff) | |
download | dotty-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.scala | 55 |
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 } } |