aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala9
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala55
-rw-r--r--tests/pos/i1130.scala6
3 files changed, 47 insertions, 23 deletions
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index ea5c28fb1..01f9f6317 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -131,8 +131,13 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
annot.derivedAnnotation(transformAnnot(annot.tree))
private def transformMemberDef(tree: MemberDef)(implicit ctx: Context): Unit = {
- tree.symbol.transformAnnotations(transformAnnot)
- Checking.checkNoPrivateLeaks(tree)
+ val sym = tree.symbol
+ sym.transformAnnotations(transformAnnot)
+ if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
+ val info1 = Checking.checkNoPrivateLeaks(sym, tree.pos)
+ if (info1 ne sym.info)
+ sym.copySymDenotation(info = info1).installAfter(thisTransformer)
+ }
}
private def transformSelect(tree: Select, targs: List[Tree])(implicit ctx: Context): Tree = {
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
}
}
diff --git a/tests/pos/i1130.scala b/tests/pos/i1130.scala
new file mode 100644
index 000000000..8d71de5e8
--- /dev/null
+++ b/tests/pos/i1130.scala
@@ -0,0 +1,6 @@
+trait A {
+ private type Foo = Int
+
+ def foo: Foo = 1
+}
+class B extends A